Reputation: 549
I'm still working on this, but figured it was worth asking about:
I have a class that conforms to the MKAnnotation
protocol called AMAnnotation
. This class also implements setCoordinate:
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
{
NSLog(@"%@ %@", self, NSStringFromSelector(_cmd));
_coordinate = newCoordinate;
}
I can successfully add the annotation to a map and I can call setCoordinate:
and the pin will move on the map. But there's a problem. Sometimes, when the map gets deallocated, the program will pause on NSKVODeallocateBreak
with the following message:
An instance 0x608000a626c0 of class AMAnnotation was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
<NSKeyValueObservationInfo 0x60800045ca70> (
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
<NSKeyValueObservance 0x600000ac0460: Observer: 0x60800038ead0, Key path: coordinate, Options: <New: NO, Old: YES, Prior: YES> Context: 0x0, Property: 0x60000045fad0>
)
I don't add any observers myself, so I overrode the KVO methods on my AMAnnotation
class. It turns out that each time I call setCoordinate:
after the annotation has been added to the map, I see the following:
<AMAnnotation: 0x60800086eac0> _original_setCoordinate:
<AMAnnotation: 0x60800086eac0> addObserver:forKeyPath:options:context: <MKMapAnnotationManager: 0x60800038d270> coordinate
Now, I don't know what _original_setCoordinate:
is, Google wasn't helpful. And it looks like the MKMapAnnotationManager
re-adds itself as an observer but isn't removing itself.
Sometimes when the map is deallocated, I see that it removes itself multiple times. But other times not at all, which is when the warnings show up.
<AMAnnotation: 0x60800086eac0> removeObserver:forKeyPath: <MKMapAnnotationManager: 0x60800038d270> coordinate
<AMAnnotation: 0x60800086eac0> removeObserver:forKeyPath: <MKMapAnnotationManager: 0x60800038d270> coordinate
<AMAnnotation: 0x60800086eac0> removeObserver:forKeyPath: <MKMapAnnotationManager: 0x60800038d270> coordinate
<AMAnnotation: 0x60800086eac0> removeObserver:forKeyPath: <MKMapAnnotationManager: 0x60800038d270> coordinate
<AMAnnotation: 0x60800086eac0> dealloc
Anyone have an explanation for this? Thanks.
Upvotes: 0
Views: 254
Reputation: 549
I hate when this happens, but it looks like I solved it. It seems that the MKMapAnnotationManager
gets confused when updating an annotation with an invalid coordinate. (At least, that's what I've observed while debugging this problem.) If I check for invalid coordinates before updating the annotation and remove the annotation if it is invalid and re-add when valid, it seems to work and properly calls the add/remove observer methods as needed.
You can check for a valid coordinate with CLLocationCoordinate2DIsValid()
. Also the constant kCLLocationCoordinate2DInvalid
might come in handy.
Upvotes: 1