Освобождение, в то время как наблюдатели с ключевыми значениями все еще зарегистрированы (обратный геокодер)

17

Когда мой взгляд исчезнет, ​​я получаю следующее сообщение:

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:

(  Контекст: 0x0, свойство: 0x1e98d0 & gt; )

Код, который определяет и запускает обратное геокодирование:

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

Я попытался установить geo.delegate на nil прямо перед тем, как отклонить представление. Это было бы слишком легко. Я также пробовал:

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

Что выдает сообщение об ошибке:

* Завершение приложения из-за неперехваченного исключения «NSRangeException», причина: «Невозможно удалить наблюдателя для выбранного пути» из-за того, что он не зарегистрирован в качестве наблюдателя.

Мое представление для кода аннотации:

-(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;
}

Я как бы нажимаю кнопки и переключаю здесь переключатели, когда вращаюсь. Любая идея, что я могу здесь сделать?

    
задан mlewis54 21.02.2011 в 23:19
источник
  • Вам нужно больше узнать о своем коде, особенно ваш метод viewForAnnotation:. Ваша проблема вряд ли имеет какое-либо отношение к обратному материалу геокодирования. –  Rog 21.02.2011 в 23:25
  • Я редактировал свой вопрос, чтобы включить код viewForAnnotation. Позвольте мне знать, если вам нужно что-нибудь еще. –  mlewis54 22.02.2011 в 00:10

2 ответа

13

Здесь может быть несколько проблем. Для каждого делегата, который вы создали, вы должны очистить его в dealloc. Для каждого наблюдателя, который вы создали, вы должны очистить его, так же, как и с уведомлениями и т. Д.

Итак, ваш dealloc должен иметь (набрав веб-браузер, возможно, придется настроить):

- (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.
}

Пройдите через вашу настройку (вероятно, в viewDidLoad) и убедитесь, что вы не делаете все, что вы там делали. В частности, все, что вызывает обратный вызов.

    
ответ дан Olie 30.03.2011 в 17:53
  • Он не работает с ARC дает ошибку «Нет видимого интерфейса для MKAnnotationView объявляет селектор removeObserver» –  पवन 19.06.2013 в 08:09
  • Вы правы, как я уже сказал, «набрал браузер». Дело в том, что вам нужно очистить все внешние указатели, которые могут быть вызваны обратными вызовами. Наблюдатели-наблюдатели - это тот, который я продолжаю забывать (поэтому я должен вернуться и удалить), но, что бы это ни было, вы должны удалить всех наблюдателей. Я обновил образец кода до того, что компилирует (removeObserver: forkeyPath: является частью NSObject.) –  Olie 19.06.2013 в 18:46
2

У меня такие же проблемы с перетаскиваемыми штырьками. Я обнаружил, что следующий код решает их:

(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"];
}
}
    
ответ дан Alexey Ishkov 28.10.2011 в 13:59