iOS 5 and Reverse Geocoding


#1

Hi everyone,

I managed to get my iOS 5 MapKit app working, but I have a problem setting the title with the city and state information. You can find my project on Github: https://github.com/dyba/Whereami/tree/ios_5. While I migrated everything, I noticed the only functionality that didn’t seem to work properly was the Reverse Geocoding feature. I created the completion handler for the reverse geocoding request as a block and inserted my code for updating the title in there. See this link: https://github.com/dyba/Whereami/blob/ios_5/Whereami/MapPoint.m#L43. Any suggestions as to what I’m missing? The block never gets called.

For convenience I’ll add the code here as well:

[code]//
// MapPoint.m
// Whereami
//
// Created by Daniel Dyba on 9/30/11.
// Copyright 2011 USC. All rights reserved.
//

#import “MapPoint.h”

@implementation MapPoint

@synthesize coordinate, geocoder, title, location, taggedDate;

void (^reverseGeocodeHandler)(NSArray *, NSError *);

  • (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
    {
    self = [super init];
    if (self) {

      // Set the coordinate
      coordinate = c;
      
      // Set the title
      [self setTitle:t];
    
      // Set the subtitle
      [self subtitle];
      
      // Create ReverseGeocoder instance
      geocoder = [[CLGeocoder alloc] init];
      
      // Create a CLLocation to pass to your geocoder instance
      location = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];        
    
    
      // Submit a reverse geocoding request
      // Must accept a CLLocation
      [geocoder reverseGeocodeLocation:location completionHandler:reverseGeocodeHandler];
      
      // The block that will update the title
      reverseGeocodeHandler = ^(NSArray *placemarks, NSError *error) {
          [self setTitle:[NSString stringWithFormat:@"%@: %@, %@", [self title],
                                                                   [[placemarks lastObject] locality],
                                                                   [[placemarks lastObject] administrativeArea]]];
      };
    

    }

    return self;
    }

  • (NSString *)subtitle
    {
    taggedDate = [[NSDate alloc] init];

    return [NSDateFormatter localizedStringFromDate:taggedDate
    dateStyle:NSDateFormatterMediumStyle
    timeStyle:NSDateFormatterNoStyle];
    }

  • (void)dealloc
    {
    [geocoder release];
    [taggedDate release];
    [title release];
    [super dealloc];
    }

@end[/code]


#2

Ok, I found this thread http://forums.bignerdranch.com/viewtopic.php?f=80&t=3013 which led me to try the following:

// Submit a reverse geocoding request // Must accept a CLLocation [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { [self setTitle:[NSString stringWithFormat:@"%@: %@, %@", [self title], [[placemarks lastObject] locality], [[placemarks lastObject] administrativeArea]]]; }];
Now can someone explain why the above code works but the code below doesn’t?

        void (^reverseGeocodeHandler)(NSArray *, NSError *);

       /* more code */

        // Submit a reverse geocoding request
        // Must accept a CLLocation
        [geocoder reverseGeocodeLocation:location completionHandler:reverseGeocodeHandler];
        
        // The block that will update the title
        reverseGeocodeHandler = ^(NSArray *placemarks, NSError *error) {
            [self setTitle:[NSString stringWithFormat:@"%@: %@, %@", [self title],
                                                                     [[placemarks lastObject] locality],
                                                                     [[placemarks lastObject] administrativeArea]]];
        };

#3

I think it’s because you’re assigning the block to the variable after trying to use it. Try this and see what happens:

        void (^reverseGeocodeHandler)(NSArray *, NSError *);

       /* more code */
        
        // The block that will update the title
        reverseGeocodeHandler = ^(NSArray *placemarks, NSError *error) {
            [self setTitle:[NSString stringWithFormat:@"%@: %@, %@", [self title],
                                                                     [[placemarks lastObject] locality],
                                                                     [[placemarks lastObject] administrativeArea]]];
        };

        // Submit a reverse geocoding request
        // Must accept a CLLocation
        [geocoder reverseGeocodeLocation:location completionHandler:reverseGeocodeHandler];

Though, the convention is to pass blocks anonymously as seen in the first of your two code snippets.