I'm learning to use MapKit in my fledgling iOS app. I'm using some of my model entities as annotations (added the <MKAnnotation> protocol to their header file). I also create custom MKAnnotationViews and set the draggable property to YES.
My model object has a location property, which is a CLLocation*. To conform to the <MKAnnotation> protocol, I added the following to that object:
- (CLLocationCoordinate2D) coordinate {
return self.location.coordinate;
}
- (void) setCoordinate:(CLLocationCoordinate2D)newCoordinate {
CLLocation* newLocation = [[CLLocation alloc]
initWithCoordinate: newCoordinate
altitude: self.location.altitude
horizontalAccuracy: self.location.horizontalAccuracy
verticalAccuracy: self.location.verticalAccuracy
timestamp: nil];
self.location = newLocation;
}
- (NSString*) title {
return self.name;
}
- (NSString*) subtitle {
return self.serialID;
}
So, I have the 4 required methods. And they're pretty straightforward. When I read the apple docs on MKAnnotationView and the @draggable property, it says the following:
Setting this property to YES makes an annotation draggable by the user. If YES, the associated annotation object must also implement the setCoordinate: method. The default value of this property is NO.
And elsewhere, the MKAnnotation docs say:
Your implementation of this property must be key-value observing (KVO) compliant. For more information on how to implement support for KVO, see Key-Value Observing Programming Guide.
I have read that (brief) document, and it is not clear at all to me what I'm supposed to do to accomplish that so that the coordinate, which I'm deriving from my location property is a proper property in and of itself.
But I'm reasonably sure it's not working correctly. When I drag the pin, it moves, but then it no longer relocates when I pan the map.
UPDATE
So I tried playing with the stock MKPinAnnotationView. To do this, I simply commented out my delegate's mapView:viewForAnnotation: method. I discovered that these aren't draggable by default. I added the mapView:didAddAnnotationViews: to my delegate to set the draggable property of the added views to YES.
Once configured thus, the Pin views, as hinted by John Estropia below, seem to work fine. I decided to use the mapView:annotationView:didChangeDragState:fromOldState: delegate hook to get a closer look at what is going on:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState {
NSArray* states = @[@"None", @"Starting", @"Dragging", @"Cancelling", @"Ending"];
NSLog(@"dragStateChangeFrom: %@ to: %@", states[oldState], states[newState]);
}
For the stock pins, one will see log output that looks like this:
2014-02-05 09:07:45.924 myValve[1781:60b] dragStateChangeFrom: None to: Starting
2014-02-05 09:07:46.249 myValve[1781:60b] dragStateChangeFrom: Starting to: Dragging
2014-02-05 09:07:47.601 myValve[1781:60b] dragStateChangeFrom: Dragging to: Ending
2014-02-05 09:07:48.006 myValve[1781:60b] dragStateChangeFrom: Ending to: None
Which looks pretty logical. But if you switch to the configured MKAnnotationView, the output you will see looks like:
2014-02-05 09:09:41.389 myValve[1791:60b] dragStateChangeFrom: None to: Starting
2014-02-05 09:09:45.451 myValve[1791:60b] dragStateChangeFrom: Starting to: Ending
It misses TWO transitions, from Starting to Dragging, and from Ending to None.
So I begin to be skeptical that I need to do something different with properties. But I'm still frustrated with why this won't work.
UPDATE 2
I created my own Annotation object to stand between my model objects, which could have a property coordinate property. The behavior remains the same. It seems to be something with the MKAnnotationView.