-ObserveValueForKeyPath: ofObject: change: context: сообщение было получено, но не обработано - PullRequest
28 голосов
/ 08 ноября 2010

Я относительно новичок в КВО, поэтому есть большая вероятность, что я нарушаю какое-то фундаментальное правило.Я использую Core Data.

Мое приложение аварийно завершает работу со следующим сообщением: И я не могу понять, почему CGImage участвует в наблюдении за значением, установленным в объекте 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”.

Все, что происходит, вызывает это:

[[self measurementPointer] setMeasurementDescriptor:descriptor];

Учитывая это,

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

По сути, объекты MeasurementPointer указывают на объекты MeasurementDescriptor - и оба являются подклассами NSManagedObject.Объекты MeasurementDescriptor описывают конкретную комбинацию «измерение» и «единица измерения» (например, «Температура (° C)» или «Скорость ветра (миль в час)»).MeasurementDescriptors - это что-то вроде синглетона в том смысле, что для каждой уникальной комбинации единиц измерения существует только один.

На MeasurementPointers ссылаются другие объекты - как объекты модели, так и объекты контроллера.MeasurementPointer ссылается на MeasurementDescriptor.Многим объектам интересно знать, когда MeasurementPointer начинает ссылаться на новый / другой дескриптор MeasurementDescriptor.Такое изменение может привести, например, к изменению оси отображения графика.Или, в приведенном выше коде, может привести к тому, что дисплей измерителя покажет другой образец (из выбранного набора образцов).

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

Ответы [ 5 ]

40 голосов
/ 09 ноября 2010

У вас есть объект, который был освобожден и не переставал наблюдать другой объект. Просмотрите все ваши -addObserver... вызовы и убедитесь, что они соответствуют -removeObserver... вызовам, по крайней мере, в -dealloc и, возможно, в -viewDidUnload в зависимости от структуры вашего приложения.

7 голосов
/ 22 апреля 2015

Я увидел эту ошибку, когда отправил метод observeValueForKeyPath на super, который я не зарегистрировал в качестве наблюдателя для изменения. Apple docs говорит: «Обязательно назовите реализацию суперкласса [из observeValueForKeyPath] , если она реализует его ."

Мое исправление должно было измениться:

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

до:

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

В быстром режиме:

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) {
    }
}
3 голосов
/ 17 марта 2014

Я столкнулся с этой проблемой, случайно передав цель в качестве наблюдателя (вместо себя) следующим образом:

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

Сообщение об ошибке не помогло определить это, так что я просто подумалбуду публиковать на тот случай, если кто-то сделает то же самое.

1 голос
/ 12 апреля 2019

Я забыл добавить override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?), чтобы действительно что-то сделать с наблюдаемым keyPath.

Вот пример версии Swift.Добавьте наблюдателей в viewDidLoad и удалите их в 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")
}
1 голос
/ 29 июня 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...