2010-11-01 20 views
0

J'implémente une application basée sur MKMapView. En cela, j'utilise un observateur lorsque nous tapons sur une épingle. l'observateur est le code est suit,Obtention d'une exception lors de l'utilisation de KVO

[annView  addObserver:self 
     forKeyPath:@"selected" 
     options:NSKeyValueObservingOptionNew 
     context:@"ANSELECTED"]; 

Il travaille comme exceptées, mais un certain temps, il devient exception « EXC_BAD_ACCESS ». Mon journal est le suivant et il me montre un souvenir qui fuit. Ai-je besoin de libérer le serveur? Si je ? alors où devrais-je relâcher ça? Pouvez-vous m'aider s'il vous plaît?

An instance 0x1b21f0 of class MKAnnotationView is being deallocated while key value observers are still registered with it. Observation info is being 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: 

( Contexte: 0x2b588, propriété: 0x1acaa0>

Merci à l'avance, S.

+0

Au lieu de KVO, pourquoi ne pas simplement utiliser la méthode délégué didSelectAnnotationView? – Anna

Répondre

3

Il fonctionne en tant qu'exception, mais il obtient parfois l'exception 'EXC_BAD_ACCESS'. Mon journal est le suivant et il me montre un souvenir qui fuit. ...

An instance 0x1b21f0 of class MKAnnotationView is being deallocated while key value observers are still registered with it. 

C'est le contraire d'une fuite. Il est étant désalloué; une fuite est quand un objet ne sera jamais désaffecté.

Le problème est qu'il est désalloué alors que quelque chose d'autre l'observe encore. Tout ce qui observe encore cet objet peut également lui envoyer d'autres messages plus tard; quand c'est le cas, ces messages iront à un objet mort (causant l'accident que vous avez vu, qui s'est passé après ce message) ou à un objet différent.

Si l'objet qui observe MKAnnotationView le possède et le libère, il doit se retirer en tant qu'observateur avant de le libérer. S'il ne le possède pas, il devrait probablement.

1

Vous devez cesser d'observer la vue d'annotation avant de le libérer:

[annView removeObserver:self forKeyPath:@"selected"]; 
+0

J'ai utilisé ceci, mais j'ai quand même eu l'exception de mémoire – sekhar

+0

Ensuite, nous avons besoin de voir plus de votre code. – zoul

0

Je sais que c'est assez vieux mais je vois que ce code est beaucoup utilisé sur stackoverflow et dans d'autres dépôts, et voici une solution au problème.

Vous devez créer un NSMutableArray Ivar dans votre vue classe contrôleur pour stocker une référence à vos annotations Vue:

MyMapViewController <MKMapViewDelegate> { 
NSMutableArray *annot; 

}

lsinitialisez dans votre viewDidLoad et dans votre - (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>) annotation vous devriez ajoutez le MKAnnotationView au tableau mutable lui-même juste avant le code d'addObserver d'annView:

if(nil == annView) { 
    annView = [[MyAnnotationView alloc] initWithAnnotation:myAnnotation reuseIdentifier:identifier]; 
    [annot addObject:annView]; 
} 


[annView addObserver:self 
      forKeyPath:@"selected" 
      options:NSKeyValueObservingOptionNew 
      context:(__bridge void *)(GMAP_ANNOTATION_SELECTED)]; 

Ensuite, dans votre méthode viewDidDisappear vous pouvez itérer le tableau et supprimer manuellement tous les observateurs:

//remove observers from annotation 
for (MKAnnotationView *anView in annot){ 
    [anView removeObserver:self forKeyPath:@"selected"]; 
} 

[annot removeAllObjects]; 

[super viewDidDisappear:animated];