I am trying to encode annotations that are on a map, but I read that I am not able to encode CLLocationcoordinate2D variables. Does anyone know how I can solve this? Here is some code.
This is where I drop the pins:
- (void)press:(UILongPressGestureRecognizer *)recognizer {
CGPoint touchPoint = [recognizer locationInView:_worldView];
CLLocationCoordinate2D touchMapCoordinate = [_worldView convertPoint:touchPoint toCoordinateFromView:_worldView];
geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
//NSLog(#"reverseGeocoder:completionHandler: called");
if (error) {
//NSLog(#"Geocoder failed with error: %#", error);
} else {
CLPlacemark *place = [placemarks objectAtIndex:0];
geocodedAddress = [NSString stringWithFormat:#"%# %#, %# %#", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
value = [number intValue];
number = [NSNumber numberWithInt:value + 1];
_addressPin = [[MapPoint alloc]initWithAddress:geocodedAddress coordinate:touchMapCoordinate
title:geocodedAddress identifier:number];
NSLog(#"The identifier is %#", number);
[[Data singleton].annotations addObject:_addressPin];
[_worldView addAnnotation:_addressPin];
NSLog(#"The number of pins in the annotation array is: %u",[Data singleton].annotations.count);
}
}
}];
}
Here is my class that conforms to the MKAnnotation protcol:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MapPoint : NSObject <MKAnnotation, NSCoding>
{
}
- (id)initWithAddress:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident;
//This is a required property from MKAnnotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotataion
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) BOOL animatesDrop;
#property (nonatomic) BOOL canShowCallout;
#property (copy) NSString *address;
#property (copy) NSNumber *identifier;
#property (nonatomic, copy) NSString *imageKey;
#property (nonatomic, copy) UIImage *image;
#end
import "MapPoint.h"
#implementation MapPoint
#synthesize title, subtitle, animatesDrop, canShowCallout, imageKey, image;
#synthesize address = _address, coordinate = _coordinate, identifier = _indentifier;
-(id)initWithAddress:(NSString *)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident {
self = [super init];
if (self) {
_address = [address copy];
_coordinate = coordinate;
_indentifier = ident;
[self setTitle:t];
NSDate *theDate = [NSDate date];
subtitle = [NSDateFormatter localizedStringFromDate:theDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_address forKey:#"address"];
[aCoder encodeObject:title forKey:#"title"];
[aCoder encodeObject:_indentifier forKey:#"identifier"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
[self setAddress:[aDecoder decodeObjectForKey:#"address"]];
}
return self;
}
#end
Just encode the two fields of the CLLocationCoordinate2D value.
[aCoder encodeDouble:_coordinate.latitude forKey:#"latitude"];
[aCoder encodeDouble:_coordinate.longitude forKey:#"longitude"];
NSValue is NSCoding compliant. You can box your CLLocationcoordinate2D variable in an NSValue object:
[coder encodeObject:[NSValue valueWithMKCoordinate:coordinate] forKey:#"coordinate"]
The CLLocationCoordinate2D's latitude and longitude are of type CLLocationDegrees which is, essentially, a fancy way of saying double.
This is how you can encode and decode them:
NSString *const kPinCoordinateLatitudeKey = #"kPinCoordinateLatitudeKey";
NSString *const kPinCoordinateLongitudeKey = #"kPinCoordinateLongitudeKey";
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.coordinate.latitude forKey:kPinCoordinateLatitudeKey];
[encoder encodeDouble:self.coordinate.longitude forKey:kPinCoordinateLongitudeKey];
}
- (id)initWithCoder:(NSCoder *)decoder
{
if((self = [super init])) {
CLLocationDegrees latitude = [decoder decodeDoubleForKey:kPinCoordinateLatitudeKey];
CLLocationDegrees longitude = [decoder decodeDoubleForKey:kPinCoordinateLongitudeKey];
_coordinate = CLLocationCoordinate2DMake(latitude, longitude);
}
return self;
}
I decided to encode use a CLLocation property handle this situation, which conforms to NSSecureCoding.
If you need to convert to or from a CLLocationCoordinate2D:
// Coordinate to Location
CLLocationCoordinate2D coord;
CLLocation *loc = [[CLLocation alloc] initWithLatitude:coord.latitude
longitude:coord.longitude];
// Location to Coordinate
CLLocationCoordinate2D coord = loc.coordinate;
Related
I have to add directions among two custom locations in IOS 7.
Any one tell me please.
Thanks.
Try this:
1.Create a file named ViewController with MKMapView as an IBOutlet and connect the map view from Storyboard to MKMapView property.
[ViewController.h]
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>
#interface ViewController : UIViewController <MKMapViewDelegate>
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
#end
[ViewController.m]
#import "ViewController.h"
#import "Annotation.h"
#define Location1Latitude -12.429481
#define Location1Longitude 130.863324
#define Location2Latitude -32.15037
#define Location2Longitude 115.782909
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.delegate = self;
[self.mapView setMapType:MKMapTypeStandard];
[self.mapView setZoomEnabled:YES];
[self.mapView setScrollEnabled:YES];
//Annotation
NSMutableArray * locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Annotation * myAnn;
// Location 1 Annotation
myAnn = [[Annotation alloc] init];
location.latitude = Location1Latitude;
location.longitude = Location1Longitude;
[locations addObject:myAnn];
//Location 2 Annotation
myAnn = [[Annotation alloc] init];
location.latitude = Location2Latitude;
location.longitude = Location2Longitude;
myAnn.coordinate = location;
[locations addObject:myAnn];
[self.mapView addAnnotations:locations];
[self performSelector:#selector(drawRoute) withObject:self afterDelay:1.0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)drawRoute {
MKPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(Location1Latitude, Location1Longitude) addressDictionary:nil];
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
[srcMapItem setName:#"source"];
MKPlacemark *destination = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(Location2Latitude, Location2Longitude) addressDictionary:nil ];
MKMapItem *destMapItem = [[MKMapItem alloc]initWithPlacemark:destination];
[destMapItem setName:#"dest"];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
[request setSource:srcMapItem];
[request setDestination:destMapItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile];
MKDirections *direction = [[MKDirections alloc]initWithRequest:request];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
NSLog(#"response = %# \n eror %#",response, error);
NSArray *arrRoutes = [response routes];
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[self.mapView addOverlay:line];
NSLog(#"Rout Name : %#",rout.name);
NSLog(#"Total Distance (in Meters) :%f",rout.distance);
NSArray *steps = [rout steps];
NSLog(#"Total Steps : %lu",(unsigned long)[steps count]);
[steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Rout Distance : %f",[obj distance]);
NSLog(#"Rout Instruction : %#",[obj instructions]);
}];
}];
}];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.strokeColor = [UIColor colorWithRed:55.0/255.0 green:160.0/255.0 blue:250.0/255.0 alpha:1.0];
renderer.lineWidth = 4.0;
return renderer;
}
2.Create a file named Annotation.
[Annotation.h]
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Annotation : NSObject <MKAnnotation>
#property(nonatomic, assign) CLLocationCoordinate2D coordinate;
#property(nonatomic, copy) NSString * title;
#property(nonatomic, copy) NSString * subtitle;
#property(nonatomic, copy) NSString * imageName;
#end
[Annotation.m]
#import "Annotation.h"
#implementation Annotation
#end
In my app, I am trying to save the pins that are on the map so that they are there when the user opens the app after it is terminated. I have conformed my mkAnnotation class to NSCoding, and implemented the two required methods. The annotations are all stored in a NSMutableArray in a singleton class, so I am really just trying to save the array in the singleton class. Everything is being encoded fine, but I do not think they are being decoded. Here is some code:
This is my MKAnnotation class:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MapPoint : NSObject <MKAnnotation, NSCoding>
{
}
- (id)initWithAddress:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t;
#property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotataion
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) BOOL animatesDrop;
#property (nonatomic) BOOL canShowCallout;
#property (copy) NSString *address;
#property (nonatomic, copy) NSString *imageKey;
#property (nonatomic, copy) UIImage *image;
#end
#implementation MapPoint
#synthesize title, subtitle, animatesDrop, canShowCallout, imageKey, image;
#synthesize address = _address, coordinate = _coordinate;
-(id)initWithAddress:(NSString *)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t {
self = [super init];
if (self) {
_address = [address copy];
_coordinate = coordinate;
[self setTitle:t];
NSDate *theDate = [NSDate date];
subtitle = [NSDateFormatter localizedStringFromDate:theDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_address forKey:#"address"];
NSLog(#"ENCODING coordLatitude %f coordLongitude %f ", _coordinate.latitude, _coordinate.longitude);
[aCoder encodeDouble:_coordinate.longitude forKey:#"coordinate.longitude"];
[aCoder encodeDouble:_coordinate.latitude forKey:#"coordinate.latitude"];
[aCoder encodeObject:title forKey:#"title"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
[self setAddress:[aDecoder decodeObjectForKey:#"address"]];
NSLog(#"DECODING coordLatitude %f coordLongitude %f ", _coordinate.latitude, _coordinate.longitude);
_coordinate.longitude = [aDecoder decodeDoubleForKey:#"coordinate.longitude"];
_coordinate.latitude = [aDecoder decodeDoubleForKey:#"coordinate.latitude"];
[self setTitle:[aDecoder decodeObjectForKey:#"title"]];
}
return self;
}
#end
Here is my singleton class:
#import <Foundation/Foundation.h>
#class MapPoint;
#interface Data : NSObject
{
NSMutableArray *_annotations;
}
#property (retain, nonatomic) NSMutableArray *annotations;
+ (Data *)singleton;
- (NSString *)pinArchivePath;
- (BOOL)saveChanges;
#end
#implementation Data
#synthesize annotations = _annotations;
+ (Data *)singleton {
static dispatch_once_t pred;
static Data *shared = nil;
dispatch_once(&pred, ^{
shared = [[Data alloc] init];
shared.annotations = [[NSMutableArray alloc]init];
});
return shared;
}
- (id)init {
self = [super init];
if (self) {
NSString *path = [self pinArchivePath];
_annotations = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if (!_annotations) {
_annotations = [[NSMutableArray alloc]init];
}
}
return self;
}
- (NSString *)pinArchivePath {
NSArray *cachesDirectories = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [cachesDirectories objectAtIndex:0];
return [cachesDirectory stringByAppendingPathComponent:#"pins.archive"];
}
- (BOOL)saveChanges {
NSString *path = [self pinArchivePath];
return [NSKeyedArchiver archiveRootObject:[Data singleton].annotations
toFile:path];
}
#end
In my viewDidLoad method on the map view controller, I try and place the annotations in the singleton array on the map with this:
for (MapPoint *mp in [Data singleton].annotations) {
[_worldView addAnnotation:mp];
}
The main problem is in the singleton method in these lines:
dispatch_once(&pred, ^{
shared = [[Data alloc] init];
shared.annotations = [[NSMutableArray alloc]init]; //<-- problem line
});
The shared = [[Data alloc] init]; line decodes and initializes the annotations array.
Then the shared.annotations = [[NSMutableArray alloc]init]; line re-creates and re-initializes the annotations array thus discarding the just-decoded annotations so the singleton always returns an empty array.
Remove the shared.annotations = [[NSMutableArray alloc]init]; line.
As already mentioned in the comment, the other minor issue, which causes simply confusion, is the placement of the NSLog where the coordinate is being decoded. The NSLog should be after the decode is done.
So in my app, I have a mapView that drops pins when the screen is pressed. Once the annotations are dropped, they are placed into an array. There will be multiple pins on the map at one time, and each pin has a identifier property that is an NSNumber. I have another view controller that is pushed onto the stack when the callout button on the annotationView is pressed, and this view has a button that I want to delete the pin from the mapView when pressed. My problem is, I do not know how to pass the identifier of the pin to the second view controller. Here is some code.
This is the method where I drop the pin:
-(void)press:(UILongPressGestureRecognizer *)recognizer
{
CGPoint touchPoint = [recognizer locationInView:_worldView];
CLLocationCoordinate2D touchMapCoordinate = [_worldView convertPoint:touchPoint toCoordinateFromView:_worldView];
geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"reverseGeocoder:completionHandler: called");
if (error) {
NSLog(#"Geocoder failed with error: %#", error);
} else {
CLPlacemark *place = [placemarks objectAtIndex:0];
geocodedAddress = [NSString stringWithFormat:#"%# %#, %# %#", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
value = [number intValue];
number = [NSNumber numberWithInt:value + 1];
addressPin = [[MapPoint alloc]initWithAddress:geocodedAddress coordinate:touchMapCoordinate
title:geocodedAddress identifier:number];
NSLog(#"The identifier is %#", number);
[_annotationArray addObject:addressPin];
[_worldView addAnnotation:addressPin];
NSLog(#"The number of pins in the annotation array is: %u",_annotationArray.count);
}
}
}];
}
This is where I create the second view controller:
-(void)mapView:(MKMapView *)mapView
annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
PinViewController *pinViewController = [[PinViewController alloc]init];
[[self navigationController]pushViewController:pinViewController animated:YES];
pinViewController.label.text = view.annotation.title;
}
Here is my MKAnnotation class:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MapPoint : NSObject <MKAnnotation>
{
NSString *_address;
CLLocationCoordinate2D _coordinate;
NSNumber *_identifier;
}
- (id)initWithAddress:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident;
//This is a required property from MKAnnotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotataion
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) BOOL animatesDrop;
#property (nonatomic) BOOL canShowCallout;
#property (copy) NSString *address;
#property (copy, nonatomic) NSNumber *identifier;
#end
#import "MapPoint.h"
#implementation MapPoint
#synthesize title, subtitle, animatesDrop, canShowCallout;
#synthesize address = _address, coordinate = _coordinate, identifier = _identifier;
-(id)initWithAddress:(NSString *)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident
{
self = [super init];
if (self) {
_address = [address copy];
_coordinate = coordinate;
_identifier = ident;
[self setTitle:t];
NSDate *theDate = [NSDate date];
subtitle = [NSDateFormatter localizedStringFromDate:theDate
dateStyle:NSDateFormatterMediumStyle
timeStyle:NSDateFormatterMediumStyle];
}
return self;
}
#end
Try following:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
MyAnnotation *myAnnotation = view.annotation;
}
Just add it as a property in your SecondViewController:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
PinViewController *pinViewController = [[PinViewController alloc]init];
[[self navigationController]pushViewController:pinViewController animated:YES];
pinViewController.label.text = view.annotation.title;
pinViewController.annotation_id = view.annotation.some_id;
}
Add segue from your first ViewController Try to second ViewController and do check your class like following:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
[self performSegueWithIdentifier: #"segue_name" sender: view];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString: #"segue_name"]) {
SecondViewController *vc = segue.destinationViewController;
vc.variable_name = view.annotation.title;
MyAnnotation vc.annotation_id*myAnnotation = view.annotation.some_id;
}annotation;
}
I have a mapView where users press to drop a pin. There may be multiple pins at one time, and each annotation view has a callout that pushes a new view to the stack when it is pressed. What I want to do is pass the title of the annotation view to the label in the second view.
Here is the code where I drop the pin:
-(void)press:(UILongPressGestureRecognizer *)recognizer
{
CGPoint touchPoint = [recognizer locationInView:worldView];
CLLocationCoordinate2D touchMapCoordinate = [worldView convertPoint:touchPoint toCoordinateFromView:worldView];
geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"reverseGeocoder:completionHandler: called");
if (error) {
NSLog(#"Geocoder failed with error: %#", error);
} else {
CLPlacemark *place = [placemarks objectAtIndex:0];
address = [NSString stringWithFormat:#"%# %#, %# %#", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
addressPin = [[MapPoint alloc]initWithCoordinate:touchMapCoordinate
title:address];
[worldView addAnnotation:addressPin];
}
}
}];
}
And here is the code where I call the second view:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
PinViewController *pinViewController = [[PinViewController alloc]init];
[self passValues];
[[self navigationController]pushViewController:pinViewController animated:YES];
}
You can override MKAnnotation (for example MyLocation)and declare in MyLocation.h file
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyLocation : NSObject <MKAnnotation> {
NSNumber *identyfier;
NSString *_name;
NSString *_address;
CLLocationCoordinate2D _coordinate;
}
#property (copy) NSString *name;
#property (copy) NSString *address;
#property (copy) NSNumber *identyfier;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithName:(NSString*)name address:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate identyfier:(NSNumber *) identyfier;
#end
in MyLocation.m file:
#import "MyLocation.h"
#implementation MyLocation
#synthesize name = _name;
#synthesize address = _address;
#synthesize coordinate = _coordinate;
#synthesize identyfier = _identyfier;
- (id)initWithName:(NSString*)name address:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate identyfier:(NSNumber *)identyfier {
if ((self = [super init])) {
_name = [name copy];
_address = [address copy];
_coordinate = coordinate;
_identyfier = identyfier;
}
return self;
}
In your map view when you declare annotation use this methos:
MyLocation *pin = [[MyLocation alloc] initWithName:place.name address:place.address coordinate:coordinate2D identyfier:some_id];
So for example in your map delegate:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
you can use:
((MyLocation *)annotation).identyfier
to check selected annotation (of course you can use different variables in MyLocation class)
Usually when i need to pass variables i just create a global variable that then can be read by both view.
There is the
extern (NSString *)some_variable_name, which you put in the .h file and in the .m file you globally put (NSString *)some_variable_name ;
Which the can be read by all views
Or the + sign in front of you variable, which then can be read by all views that includes the view (setting the global at the top in the .m file, and in the .h file by the comman
something = [someview that_variable] ;
I currently have an XML model getting processed my an NSXMLParser; I get about 340 objects in my model after processing. I place all of the objects on my MKMapView. Once a user "selects" an object (MKAnnotationViewPin); once I start off, the title is populated, coords too (duh?) but the subtitle is set to a place-holder. I process another XML file to retrieve extra information, the subtitle gets updated and populated.
Once the XML file gets parsed I get notified and update its <MKAnnotation> object to reflect the changed subtitle. To reflect the change on the map I have to "unselect" the pin and click it again for it to show the change.
Here is my <MKAnnotation> object:
Header:
#interface CPCustomMapPin : NSObject <MKAnnotation>
{
NSString *_title;
NSString *_annotation;
CLLocationCoordinate2D _coords;
NSString *stationID;
}
#property (nonatomic, retain) NSString *_title;
#property (nonatomic, retain) NSString *_annotation;
#property (nonatomic) CLLocationCoordinate2D _coords;
#property (nonatomic, retain) NSString *stationID;
- (id) initWithTitle: (NSString *) _title withAnnotation: (NSString *) _annotation withCoords: (CLLocationCoordinate2D) _coords withStationID: (NSString *) _id;
Implementation:
#implementation CPCustomMapPin
#synthesize _title, _annotation, _coords, stationID;
- (id) initWithTitle: (NSString *) __title withAnnotation: (NSString *) __annotation withCoords: (CLLocationCoordinate2D) __coords withStationID: (NSString *) _id
{
_title = [[NSString alloc] init];
_annotation = [[NSString alloc] init];
stationID = [[NSString alloc] init];
[self set_title: __title];
[self set_annotation: __annotation];
[self set_coords: __coords];
[self setStationID: _id];
return self;
}
- (NSString *) title
{
return _title;
}
- (NSString *) subtitle
{
return _annotation;
}
- (CLLocationCoordinate2D) coordinate
{
return _coords;
}
- (NSString *) description
{
return [NSString stringWithFormat: #"title: %# subtitle: %# id: %#", _title, _annotation, stationID];
}
- (void) dealloc
{
[_title release];
[_annotation release];
[stationID release];
[super dealloc];
}
#end
Thank you for your valuable input.
Apparently no one knows… I just found this technique:
- (void) closeAnnotation: (id <MKAnnotation>) annotation inMapView: (MKMapView *) mapView
{
[mapView deselectAnnotation: annotation animated: NO];
[mapView selectAnnotation: annotation animated: YES];
}
And of course you call your method accordingly:
Example:
- (void) myMethod
{
for (id <MKAnnotation> _annotation in mapView.annotations)
{
[self closeAnnotation: _annotation inMapView: mapView];
}
}