Reusing Placemark Data


I reused the placemark data when the coordinates are equal for the reversegeodecoder challenge (as recommended in the documentation). It took me a while to figure out, so I thought I’d post it. The main problem I had was that the @property placemark had to be retain. Copy would crash it. I also broke the coordinate comparison down into lat/long floating numbers to compare them. Is there a better way? I’m a newbie, suggestions are welcome.

note I had done the program in the book over a month ago. This is a different version, not because I think its better, but because I wanted to try it without looking at the answer. This is what I came up with.

[code]#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface WhereAmiAppDelegate : NSObject <UIApplicationDelegate, MKMapViewDelegate, CLLocationManagerDelegate> {
UIWindow *window;
IBOutlet MKMapView *mapView;
IBOutlet UIActivityIndicatorView *spinner;
IBOutlet UITextField *textField;
CLLocationManager *locationManager;
@property (nonatomic, retain) IBOutlet UIWindow *window;

[code]#import “WhereAmiAppDelegate.h”
#import “MapPoint.h”

@implementation WhereAmiAppDelegate

@synthesize window;

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    locationManager = [[CLLocationManager alloc]init];
    [locationManager setDelegate:self];
    [locationManager startUpdatingLocation];
    [mapView setShowsUserLocation:YES];
    [window makeKeyAndVisible];
    return YES;
  • (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    NSLog(@“did update location”);
    if ([[newLocation timestamp] timeIntervalSinceNow]<-180)
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([newLocation coordinate], 200, 200);
    [mapView setRegion:region animated:YES];
  • (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    NSLog(@“locationManager failed:%@”,error);
  • (BOOL)textFieldShouldReturn:(UITextField *)t
    NSLog(@“pressed return”);
    [textField resignFirstResponder];
    uLocation = [mapView userLocation];
    NSDateFormatter *format =[[NSDateFormatter alloc]init];
    [format setDateStyle:NSDateFormatterMediumStyle];
    [format setTimeStyle:NSDateFormatterMediumStyle];
    MapPoint *mapPoint = [[MapPoint alloc]initWithTitle:[t text] subtitle:[format stringFromDate:[NSDate date]] coordinate:uLocation.coordinate];
    BOOL b = NO;
    NSArray *a = [mapView annotations];
    for (int i = [a count]-1;i>=0;i–)
    MapPoint *ann=[a objectAtIndex:i];
    NSLog(@“number of annotations:%i”,[a count]);
    NSLog(@“current annotation class:%@, description%@”,[ann class],[ann description]);
    if (![ann isMemberOfClass:[MapPoint class]])
    if ((mapPoint.coordinate.latitude == ann.coordinate.latitude) && (mapPoint.coordinate.longitude == ann.coordinate.longitude) &&([ann placemark]))
    MKPlacemark *pm = [ann placemark];
    [mapPoint setPlacemark:pm];
    NSString *s = [[NSString alloc] initWithFormat:@"%@ %@, %@", [mapPoint title], [pm locality], [pm administrativeArea]];
    [mapPoint setTitle:s];
    [s release];
    if (b==NO)
    MKReverseGeocoder *geo = [[MKReverseGeocoder alloc]initWithCoordinate:mapPoint.coordinate];
    [geo setDelegate];
    [geo start];
    [mapView addAnnotation];
    [mapPoint release];
    [format release];
    [t setText:@""];
    return YES;
  • (void)dealloc {
    [locationManager release];
    [window release];
    [super dealloc];

[code]#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface MapPoint : NSObject<MKAnnotation,MKReverseGeocoderDelegate>
NSString *title, *subtitle;
CLLocationCoordinate2D coordinate;
MKPlacemark *placemark;

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title, *subtitle;
@property (nonatomic, assign) MKPlacemark *placemark;

-(id) initWithTitle: (NSString*)t subtitle: (NSString*)s coordinate: (CLLocationCoordinate2D) c;


[code]#import “MapPoint.h”

@implementation MapPoint
@synthesize title, subtitle, coordinate, placemark;

-(id) initWithTitle: (NSString*)t subtitle: (NSString*)s coordinate: (CLLocationCoordinate2D) c
NSLog(@“mappoint init”);
[super init];
coordinate = c;
[self setTitle:t];
[self setSubtitle:s];
return self;

  • (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)p
    NSLog(@“did find placemark”);
    placemark = p;
    NSString *s = [[NSString alloc] initWithFormat:@"%@, %@ %@", title, [placemark locality], [placemark administrativeArea]];

    [self setTitle:s];
    [s release];
    [geocoder release];

  • (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError )error
    NSLog(@“reverseGeocoder failed with error:%@”,error);
    ) description
    NSString *d = [NSString stringWithFormat:@“title:%@ subtitle:%@ coordinate.latitude:%f coordinate.longitude:%f placemark:%@”,title, subtitle,coordinate.latitude,coordinate.longitude, [placemark locality]];
    return d;


  • (void) dealloc
    [title release];
    [subtitle release];
    [super dealloc];