Question

I'm trying to understand CLPlacemark and when/how to create information for a callout of a pin that is added to a map. Before what I read in More iOS 3 development a few years ago, they reverse geocoded an address and built the address (street, zip, state, etc). First, do I need to build this string myself? I was trying to find out how to get the name of a location for certain known things like searching for the apple store in the code below:

NSString *address = @"1 stockton, san francisco, ca";    
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
        [geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {

    [placemarks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"obj description: %@", [obj description]);

        CLPlacemark *aPlacemark = (CLPlacemark *)obj;
        NSLog(@"%@", [aPlacemark.addressDictionary description]);
        NSLog(@"name: %@", ((CLPlacemark *)obj).name);
    }];
];

When I print out the description, I see that the Console says:

Apple Store, San Francisco, 1 Stockton St, San Francisco, CA  94108-5805, United States @ <+37.78584545,-122.40651752> +/- 100.00m, region (identifier <+37.78584545,-122.40652161> radius 18.96) <+37.78584545,-122.40652161> radius 18.96m

Where does it get the Apple Store, San Francisco, name? I thought it would be the CLPlacemark.name property, but that is null. So in trying to figure out how the name property is created, I found:

        NSLog(@"%@", [aPlacemark.addressDictionary description]);

I get the output:

City = "San Francisco";
Country = "United States";
CountryCode = US;
FormattedAddressLines =     (
    "Apple Store, San Francisco",
    "1 Stockton St",
    "San Francisco, CA  94108-5805",
    "United States"
);
PostCodeExtension = 5805;
State = California;
Street = "1 Stockton St";
SubAdministrativeArea = "San Francisco";
SubLocality = "Union Square";
SubThoroughfare = 1;
Thoroughfare = "Stockton St";
ZIP = 94108;

From this, all I can see is that in the FormattedAddressLines key of the addressDictionary, the title is there as well.

So I guess my 2 questions are:

1) How do I get the name of a location if there is one (i.e. Apple Store)?

2) Do I need to build my string anymore since it seems like the address dictionary does that for me already?

Thanks!

Was it helpful?

Solution

To answer your first question, use the areasOfInterest property of the CLPlacemark.

As for the second question, thats really up to you, and how you want to format the string. If you want to build it using strings from the addressDictionary property, then by all means do so. You can pick and choose the parts, and create a string all in the completion handler.

Also, you mentioned you want to create an annotation for displaying on a map. I personally subclass MKAnnotation, and use that to quickly create an annotation to display on a map.

MyAnnotation.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MyAnnotation : NSObject <MKAnnotation> {
    NSString *_name;
    NSString *_address;
    CLLocationCoordinate2D _coordinate;
}

@property (copy) NSString *name;
@property (copy) NSString *address;
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate;

@end

MyAnnotation.m

#import "MyAnnotation.h"

@implementation MyAnnotation
@synthesize name = _name;
@synthesize address = _address;
@synthesize coordinate = _coordinate;

- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate
{
    if ((self = [super init])) {
        _name = [name copy];
        _address = [address copy];
        _coordinate = coordinate;
    }
    return self;
}

- (NSString *)title
{
    return _name;
}

- (NSString *)subtitle
{
    return _address;
}

@end

Declare an NSMutableArray to hold all the annotations, and throw the initWithName:address:coordinate: in your completion handler, and you can quickly get an array of annotations you can add to your map.

NSString *address = @"1 stockton, san francisco, ca";    
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) 
{
   NSMutableArray *annotationArray = [NSMutableArray array];
   for (CLPlacemark *aPlacemark in placemarks)
   {
      NSString *nameString = // Get your name from an array created by aPlacemark.areasOfInterest;
      NSString *addressString = // Put your address string info you get from the placemark here.
      CLLocationCoordinate2D coordinate = aPlacemark.location.coordinate;
      MyAnnotation *annotation = [[MyAnnotation alloc] initWithName:nameString address:addressString coordinate:coordinate];
      [annotationArray addObject:annotation];
   }
   // Now save annotationArray if you want to use it later
   // Add it to your MapView with [myMapView addAnnotations:annotationArray];
}];

Hope that helps out!

OTHER TIPS

You can use ABCreateStringWithAddressDictionary function from AddressBookUI framework to get the address string from CLPlacemark's "addressDictionary" property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top