2010-11-08 19 views
24

Soy relativamente nuevo en KVO, por lo que hay muchas posibilidades de que esté infringiendo alguna regla fundamental. Estoy usando Core Data.An -observeValueForKeyPath: ofObject: change: context: se recibió el mensaje pero no se manejó

Mi aplicación se bloquea con el siguiente mensaje: Y lo que no puedo entender es por qué una CGImage se está involucrando en la observación de un valor que se establece en un objeto MeasurementPointer.

 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<CGImage 0x276fc0>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled. 
Key path: measurementDescriptor 
Observed object: <MeasurementPointer: 0x8201640> (entity: MeasurementPointer; id: 0x8200410 <x-coredata://EBEE0687-D67D-4B03-8C95-F4C60CFDC20F/MeasurementPointer/p75> ; data: { 
    measurementDescriptor = "0x260fd0 <x-coredata://EBEE0687-D67D-4B03-8C95-F4C60CFDC20F/MeasurementDescriptor/p22>"; 
}) 
Change: { 
    kind = 1; 
    new = "<MeasurementDescriptor: 0x262530> (entity: MeasurementDescriptor; id: 0x260fd0 <x-coredata://EBEE0687-D67D-4B03-8C95-F4C60CFDC20F/MeasurementDescriptor/p22> ; data: {\n measurementName = Temperature;\n measurementUnits = \"\\U00b0C\";\n sortString = nil;\n})"; 
} 
Context: 0x0' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x30897ed3 __exceptionPreprocess + 114 
    1 libobjc.A.dylib      0x3002f811 objc_exception_throw + 24 
    2 CoreFoundation      0x30897d15 +[NSException raise:format:arguments:] + 68 
    3 CoreFoundation      0x30897d4f +[NSException raise:format:] + 34 
    4 Foundation       0x34a13779 -[NSObject(NSKeyValueObserving) observeValueForKeyPath:ofObject:change:context:] + 60 
    5 Foundation       0x349b6acd NSKeyValueNotifyObserver + 216 
    6 Foundation       0x349b6775 NSKeyValueDidChange + 236 
    7 Foundation       0x349ae489 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 76 
    8 CoreData       0x3165b577 _PF_ManagedObject_DidChangeValueForKeyIndex + 102 
    9 CoreData       0x3165ac51 _sharedIMPL_setvfk_core + 184 
    10 CoreData       0x3165dc83 _svfk_0 + 10 
    11 SPARKvue       0x000479f1 -[MeasurementViewController doneAction:] + 152 
    12 CoreFoundation      0x3083f719 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24 
    13 UIKit        0x31eb1141 -[UIApplication sendAction:to:from:forEvent:] + 84 
    14 UIKit        0x31f08315 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 92 
    15 CoreFoundation      0x3083f719 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24 
    16 UIKit        0x31eb1141 -[UIApplication sendAction:to:from:forEvent:] + 84 
    17 UIKit        0x31eb10e1 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32 
    18 UIKit        0x31eb10b3 -[UIControl sendAction:to:forEvent:] + 38 
    19 UIKit        0x31eb0e05 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 356 
    20 UIKit        0x31eb1453 -[UIControl touchesEnded:withEvent:] + 342 
    21 UIKit        0x31eafddd -[UIWindow _sendTouchesForEvent:] + 368 
    22 UIKit        0x31eaf757 -[UIWindow sendEvent:] + 262 
    23 UIKit        0x31eaa9ff -[UIApplication sendEvent:] + 298 
    24 UIKit        0x31eaa337 _UIApplicationHandleEvent + 5110 
    25 GraphicsServices     0x31e4504b PurpleEventCallback + 666 
    26 CoreFoundation      0x3082cce3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26 
    27 CoreFoundation      0x3082cca7 __CFRunLoopDoSource1 + 166 
    28 CoreFoundation      0x3081f56d __CFRunLoopRun + 520 
    29 CoreFoundation      0x3081f277 CFRunLoopRunSpecific + 230 
    30 CoreFoundation      0x3081f17f CFRunLoopRunInMode + 58 
    31 GraphicsServices     0x31e445f3 GSEventRunModal + 114 
    32 GraphicsServices     0x31e4469f GSEventRun + 62 
    33 UIKit        0x31e51123 -[UIApplication _run] + 402 
    34 UIKit        0x31e4f12f UIApplicationMain + 670 
    35 SPARKvue       0x000031ff main + 70 
    36 SPARKvue       0x000031b4 start + 40 
) 
terminate called after throwing an instance of 'NSException' 
Program received signal: “SIGABRT”. 

todo lo que sucede a desencadenar esto es:

[[self measurementPointer] setMeasurementDescriptor:descriptor]; 

Ante esto,

[[meterDisplay measurementPointer] addObserver:self 
      forKeyPath:@"measurementDescriptor" 
      options:NSKeyValueObservingOptionNew 
      context:nil]; 

Básicamente, MeasurementPointer objetos de punto a MeasurementDescriptor objetos - y ambos son subclases NSManagedObject. Los objetos MeasurementDescriptor describen una combinación específica de "medición" y "unidad" (p. Ej., "Temperatura (° C)" o "Velocidad del viento (mph)". Los descriptores de medición son algo así como singletons en la medida en que solo hay uno para cada combo único de unidad de medida.

Los objetos MeasurementPointers son referenciados por otros objetos, tanto Model como Controller. Un MeasurementPointer hace referencia a un MeasurementDescriptor. Muchos objetos están interesados ​​en saber cuándo un MeasurementPointer comienza a hacer referencia a un MeasurementDescriptor nuevo/diferente. Tal cambio podría causar que el eje de una pantalla gráfica cambie, por ejemplo. O bien, en el código anterior, podría hacer que una pantalla muestre una muestra diferente (de un conjunto seleccionado de muestras).

Creo que el problema fundamental es que un CGImage está recibiendo un mensaje que no está destinado a él ... desafortunadamente, esto es intermitente, por lo que no he podido encontrar un patrón que lo desencadene.

+1

Esto es probablemente debido a una liberación excesiva en otro lugar.El CGImage se asignó en el lugar donde debería haber estado el otro objeto. –

+0

Eso era lo que temía ... lo extraño es que es * siempre * una CGImage. O, al menos, hoy fue CGImage 6 o 7 veces. Supongo que encenderé NSZombieEnabled y verifico esto. Gracias. – westsider

Respuesta

36

Tiene un objeto que se desasoció y no dejó de observar otro objeto. Repase todas sus llamadas -addObserver... y asegúrese de que coincidan con las llamadas -removeObserver... al menos en -dealloc y posiblemente en -viewDidUnload según la estructura de su aplicación.

+1

tienes razón. No fue un problema de Datos centrales. Debería haber publicado antes, pero arreglar este problema descubrió otro. Con NSZombieEnabled activado, pude obtener una advertencia útil sobre los objetos desasignados que se envían mensajes. – westsider

+0

Me enteré de esto al usar un código de demostración que no estaba escrito para des-observar correctamente algo cuando desapareció. Google me trajo aquí mismo. Salve el poderoso Google. –

+0

Mi aplicación usa ARC donde eliminar al observador? –

1

Tuve el mismo problema, pero en mi caso estaba observando un contexto diferente. Luego puse todo en el mismo contexto y el accidente se fue. Espero que esto ayude a alguien.

3

me encontré con este problema al pasar accidentalmente el objetivo de que el observador (en lugar de uno mismo), así:

[self.someView addObserver:self.someView forKeyPath:@"key" options:0 context:nil]; 

El mensaje de error no fue del todo útil en la identificación de este modo sólo pensé publicar en caso de que alguien más haga lo mismo.

6

vi este error cuando envié el método observeValueForKeyPath a super, que no había registrado como un observador para el cambio. Apple docs decir "Asegúrese de llamar a la implementación de la superclase [de observeValueForKeyPath] si lo implementa."

Mi solución fue cambiar:

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context { 
    if ([keyPath isEqualToString:kPropertyThatChanges]) { 
    ... 
    } 
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
} 

a:

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context { 
    if ([keyPath isEqualToString:kPropertyThatChanges]) { 
    ... 
    } 
} 
+0

Creo que esta respuesta es tan válida como la respuesta aceptada. – danh

+0

No debe eliminar la llamada a 'super', arriesgando que KVO desde otra keyPath no funcione si' super' también está observando. Lo que debe hacer es poner a llamar '' super' en el lado else' '' ' si ([keyPath isEqualToString: kPropertyThatChanges]) {... } else { [súper observeValueForKeyPath: keyPath ofObject: Objeto cambio: cambiar contexto: contexto]; } –

Cuestiones relacionadas