¿Qué causa que se genere esta exception "error de observador"?

Solo obtengo este error si es iOS 7 y si incluyo un map personalizado de spcluster (superpolo map). ¿Por qué ocurre este error y cómo lo soluciono?

*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MKMapAnnotationManager 0xb355a00> for the key path "coordinate" from <Annotation 0x194c1470> because it is not registenetworking as an observer.' 

Tuve este mismo problema.

Puedes resolverlo haciendo esto.

  1. Cree una subclass de MKAnnotation o agregue lo siguiente a su subclass existente.
  2. En él, agrega una variable (esto está en Swift pero también puedes interpretar esto para ObjC):
  var observers: NSMutableSet! = NSMutableSet() 
  1. Luego, agregue los siguientes methods:
  override func addObserver(observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions, context: UnsafeMutablePointer) { let observerId : String = "\(observer.hashValue)\(keyPath)" self.observers.addObject(observerId) super.addObserver(observer, forKeyPath: keyPath, options: options, context: context) } override func removeObserver(observer: NSObject, forKeyPath keyPath: String) { let observerId : String = "\(observer.hashValue)\(keyPath)" if (self.observers.containsObject(observerId)) { self.observers.removeObject(observerId) super.removeObserver(observer, forKeyPath: keyPath) } } 
  1. Use esta subclass con su MKMapView.

Para la debugging, si agrega una instrucción "NSLog" dentro de un bloque else en removeObserver (), puede ver que, ocasionalmente, MKMapView (o su MKAnnotationManager) decidirá aleatoriamente eliminar la observación de una notificación MKAn que ya se pidió que se eliminara la observación. Esto es, de acuerdo con la propia documentation de KVO de Apple, que no debe hacerse.

Estas anulaciones "arreglan" el problema, ya que rastrean (en base a annotations) qué observaciones ya se han registrado para cada anotación, lo que le permite negarse a dejar de observar algo que ya no se observó (o nunca lo fue) observado en primer lugar).

Es kludgy, pero arreglaron mi crash de animation. Y hágalo sin demasiados gastos de performance.

En mi experiencia, una causa común de esto es que las coordinate se observaban a través de una ruta de key de elementos múltiples y que una de las keys intermedias se modificaba de forma no compatible con KVO. Esto deja a la maquinaria interna de KVO observar una cosa cuando piensa que está observando algo diferente. Algún time después, cuando una parte de la ruta key se cambia de una manera compatible con KVO, esta exception se eleva.

Usted (o quienquiera que haya desarrollado ese componente) está tratando de eliminar MKMapAnnotationManager como un observador de Annotation (para la coordinate ruta de key), llamando a removeObserver:forKeyPath:context: Sin embargo, MKMapAnnotationManager no está registrado como un observador, de ahí el locking.

La solución es garantizar que las llamadas a addObserver / removeObserver estén siempre en equilibrio.

Sin más detalles es todo lo que se puede decir.

Como reference adicional, aquí hay una cita relevante de este bonito artículo de blog sobre KVO :

Tal vez la molestia más profunda sobre KVO es que si hace una llamada a – removeObserver:forKeyPath:context: cuando el object no está registrado como un observador (ya sea porque ya no estaba registrado o no está registrado en primer lugar), arroja un exception. ¡El pateador es que no hay una forma incorporada para incluso comprobar si un object está registrado!

He tenido un problema más genérico con este error de observador al usar solo annotations clásicas en un MKMapView.

Cuando intentaba ejecutar mMapView.removeAnnotations(mMapView.annotations) , me topé aleatoriamente con este locking.

Solo cambielo a:

 for annotation in mMapView.annotations { mMapView.deselectAnnotation(annotation as! MKAnnotation, animated: false) mMapView.removeAnnotation(annotation as! MKAnnotation) } 

resuelto mi problema

Puedo relacionarlo con el comentario de @Aurelien Porte.

Encontré este error al usar algún código provisto por la documentation de apple para agrupar annotations MKMapView. Se puede encontrar en el proyecto de muestra PhotoMap.

Mi problema fue que la vista padre y MKMapView se desasignaron antes de que la animation terminara. La animation estaba animando las coorderadas de anotación (movía las annotations en el map)

 for (MyMKAnnotation *annotation in filtenetworkingAnnotationsInBucket) { // give all the other annotations a reference to the one which is representing them annotation.clusterAnnotation = annotationForGrid; annotation.containedAnnotations = nil; // remove annotations which we've decided to cluster if ([visibleAnnotationsInBucket containsObject:annotation]) { CLLocationCoordinate2D actualCoordinate = annotation.coordinate; // This is the flag that I added to disable/enable animation if (animateMarkerClustering) { // This animation is not finished properly before the annotationViews // animation gets finished [UIView animateWithDuration:0.3 animations:^{ annotation.coordinate = annotation.clusterAnnotation.coordinate; } completion:^(BOOL finished) { annotation.coordinate = actualCoordinate; [_mapView removeAnnotation:annotation]; }]; } else { annotation.coordinate = actualCoordinate; [_mapView removeAnnotation:annotation]; } } } 

Traté de eliminar la animation en [self.view removeAllAnimations]

y

 if (_mapView.annotations.count > 0){ NSArray *annotations =_mapView.annotations; for(int i=0;i<annotations.count;i++){ id <MKAnnotation> annotation = annotations[i]; [[_mapView viewForAnnotation:annotation].layer removeAllAnimations]; [_mapView removeAnnotation:annotation]; } //[_mapView removeAnnotations:_mapView.annotations]; } 

No he logrado nada

Por el momento, establezco animateMarkerClustering=NO para deshabilitar las animaciones de anotación, y eso funciona. No hay error.

Bien, todavía no tengo suficiente reputación para comentar la pregunta, pero resolví mi mismo caso con esta respuesta: https://stackoverflow.com/a/31231307/2248650

También como slava, estoy usando el proyecto de ejemplo PhotoMap de Apple como base para mi implementación, pero también lo he transferido a Swift. También tengo MKAnnotation subclasificada y para habilitar sus animaciones de coorderadas como en la muestra, tuve que establecer una palabra key dinámica para coordinar:

 dynamic var coordinate: CLLocationCoordinate2D 

Y ahora, como se presenta, cuando deselecciono las annotations antes de eliminarlas de este modo

 for annotation in allAnnotationsMapView.annotations { allAnnotationsMapView.deselectAnnotation(annotation, animated: false) allAnnotationsMapView.removeAnnotation(annotation) } 

Ya no encuentro la exception.