Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deallocation while key value observers still registered (reverse geocoder)

When my view goes away I get the following message:

An instance 0x1c11e0 of class MKAnnotationView 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:

( Context: 0x0, Property: 0x1e98d0> )

The code that defines and starts the reverse geocoding is:

geo=[[MKReverseGeocoder alloc] initWithCoordinate:droppedAt];
        geo.delegate=self;
        [geo start];

I have tried setting geo.delegate to nil right before the I dismiss the view. That would be too easy. I have also tried:

for (id <MKAnnotation> annotation in mvMap.annotations) {
    [[mvMap viewForAnnotation:annotation] removeObserver:self forKeyPath:@"selected"];
}

Which throws an error that says:

* Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer for the key path "selected" from because it is not registered as an observer.

My view for annotation code is:

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    MKAnnotationView *aView;

    aView=(MKAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:annotation.title];
    if (aView==nil) 
        aView=[[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotation.title] autorelease];
    else
        aView.annotation=annotation;
    [aView setImage:[UIImage imageNamed:selIcon]];
    aView.canShowCallout=TRUE;
    aView.draggable=YES;
    return aView;
}

I'm sort of pushing buttons and flipping switches here while spinning in. Any idea of what I can do here?

like image 567
mlewis54 Avatar asked Feb 21 '11 22:02

mlewis54


2 Answers

You may have multiple issues, here. For every delegate you set up, you should clear it at dealloc. For every observer you set up, you should clear that, same with Notifications, etc.

So your dealloc should have (typed in web browser, you may have to adjust):

- (void) dealloc
{
     [[NSNotificationCenter defaultCenter] removeObserver: self];
     for (id <MKAnnotation> annotation in mvMap.annotations)
     {
          // remove all observers, delegates and other outward pointers.
          [[mvMap viewForAnnotation:annotation] removeObserver: self forKeyPath: path];
     }

     gel.delegate = nil;
     // etc., your other stuff
     [super dealloc];  // Only in non-ARC legacy code.  Modern stuff skips this.
}

Go through your setup (likely in viewDidLoad) and make sure that you un-do everything that you did in there. Specifically anything that triggers a callback.

like image 196
Olie Avatar answered Oct 06 '22 01:10

Olie


I have got the same troubles with draggable pins. I have found that the following code solves them:

(void)mapView:(MKMapView *)theMapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState {

if (newState == MKAnnotationViewDragStateStarting) {

    // some my code

} else if (newState == MKAnnotationViewDragStateCanceling) {

    [annotationView removeObserver:theMapView forKeyPath:@"dragState"];

} else if (newState == MKAnnotationViewDragStateEnding) {

    [annotationView removeObserver:theMapView forKeyPath:@"dragState"];
}
}
like image 42
Alexey Ishkov Avatar answered Oct 06 '22 02:10

Alexey Ishkov