Un -observeValueForKeyPath: ofObject: el cambio: contexto: mensaje fue recibido, pero no se manejan

StackOverflow https://stackoverflow.com/questions/4120539

Pregunta

Yo soy relativamente nuevo en MVA, así que hay una buena probabilidad de que estoy violando alguna regla fundamental. Estoy usando datos básicos.

Mi aplicación se bloquea con el siguiente mensaje:. Y lo que no puedo entender es por qué un 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 está sucediendo 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 objetos MeasurementDescriptor - y ambos son subclases NSManagedObject. MeasurementDescriptor objetos describen una 'medición' y la combinación de 'unidad' (por ejemplo, "Temperatura (° C)" o "velocidad del viento (mph)") específico. MeasurementDescriptors son algo así como únicos en la medida en que sólo hay una para cada combinación de medición de unidad única.

MeasurementPointers son referenciados por otros objetos - objetos tanto del modelo y de objetos del controlador. Un MeasurementPointer hace referencia a un MeasurementDescriptor. Muchos objetos están interesados ??en saber cuando un MeasurementPointer comienza referencia a una nueva MeasurementDescriptor / diferente. Tal cambio podría causar el eje de una pantalla gráfica de cambio, por ejemplo. O, en el código anterior, podría causar una pantalla del medidor para mostrar 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á destinada a ella ... por desgracia, esto es intermitente, así que no he podido encontrar un patrón que lo activa.

¿Fue útil?

Solución

Usted tiene un objeto que quedó dealloc'ed y no dejó de observar otro objeto. Caminar a través de todas sus llamadas -addObserver... y asegurarse de que se hacen coincidir con las llamadas -removeObserver... al menos en la -dealloc y, posiblemente, en el -viewDidUnload dependiendo de la estructura de la aplicación.

Otros consejos

vi este error cuando envié el método observeValueForKeyPath a super, que no había registrado como un observador para el cambio. de Apple docs dicen "recuerda para llamar a la implementación de la superclase [de observeValueForKeyPath] si se 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]) {
    ...
  }
}

En rápida:

func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if (keyPath == kPropertyThatChanges) {
    }
    super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
To:
func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if (keyPath == kPropertyThatChanges) {
    }
}

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 simplemente pensé que había puesto en caso de que alguien más lo hace la misma cosa.

Yo tenía el mismo problema, pero en mi caso yo estaba observando un contexto diferente. A continuación os pongo todos en el mismo contexto y el accidente se había ido. Espero que esto ayude a alguien.

Para mí se me olvidó añadir en override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) para realmente hacer algo con conseguir observó la keyPath.

Este es un ejemplo de la versión Swift. Añadir los observadores en viewDidLoad y eliminarlos en deinit:

lazy var firstNameTextField: UITextField = {
    let textField = UITextField()
    // configure your textField
    return textField
}()

lazy var lastNameTextField: UITextField = {
    let textField = UITextField()
    // configure your textField
    return textField
}()

override func viewDidLoad() {
    super.viewDidLoad()

    // 1. add your observers here
    firstNameTextField.addObserver(self, forKeyPath: "text", options: [.old, .new], context: nil)
    lastNameTextField.addObserver(self, forKeyPath: "text", options: [.old, .new], context: nil)
}

// 2. ***IMPORTANT you must add this function or it will crash***
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    if keyPath == "text" {
        print("do something when the textField's text your observing changes")
    }
}

 // 3. remove them in deinit
deinit {
    firstNameTextField.removeObserver(self, forKeyPath: "text", context: nil)
    lastNameTextField.removeObserver(self, forKeyPath: "text", context: nil)
    print("DEINIT")
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top