Проблема KVO Невозможно удалить наблюдателя

У меня есть NSArrayController, связанный с объектом Core Data, для которого установлено автоматическое переупорядочение содержимого и фильтруется предикатом. Все хорошо, пока я не попытаюсь аннулировать отношения и назначить другие. В этот момент мое приложение вылетает, и я получаю следующую ошибку:

Невозможно удалить наблюдателя для ключевого пути "карьера.тип" из объекта, скорее всего, потому что значение ключа "карьера" изменилось без отправки соответствующего уведомления KVO. Проверьте KVO-соответствие класса Person.

Если присмотреться, похоже, что установка моего NSArrayController на автоматическое переупорядочение содержимого вызывает эту проблему. Но я пытаюсь решить проблему, не прибегая к ручной перестановке NSArrayController. Вот псевдокод, вызывающий ошибку:

object.career = nil;
object.field = (Field *)item;

Вот предикат, который использует мой NSArrayController:

(career != NIL && career == %@) || (field != NIL && field == %@)

Где% @ для обоих экземпляров - это объект CoreData.

По сути, это выглядит так, как будто у NSArrayController есть наблюдатель, установленный для object.career.type, и обнуление отношения вызывает проблему, когда этот наблюдатель автоматически удаляется. Так что мне интересно, не так ли я поступаю? Должен ли я получить копию объекта, удалить ее из MOC и повторно вставить ее с параметром карьеры, равным нулю, и соответствующим установленным полем?

Как правильно уведомить наблюдателя о том, что тип был аннулирован? Обратите внимание, что все атрибуты и отношения, упомянутые здесь, используют ванильные KVO-совместимые геттеры / сеттеры.


person ndg    schedule 28.07.2010    source источник


Ответы (1)


Из документации по яблокам

Неисправности и уведомления KVO

Когда Core Data превращает объект в неисправность, для свойств объекта отправляются уведомления об изменении значения ключа (KVO) (см. Руководство по программированию наблюдения за ключом). Если вы наблюдаете свойства объекта, который превратился в неисправность, и неисправность впоследствии была обнаружена, вы получаете уведомления об изменении для свойств, значения которых фактически не изменились.

Хотя значения не меняются семантически с вашей точки зрения, буквальные байты в памяти изменяются по мере материализации объекта. Механизм наблюдения "ключ-значение" требует, чтобы Core Data выдавала уведомление всякий раз, когда значения меняются, как это рассматривается с точки зрения сравнения указателей. KVO нужны эти уведомления для отслеживания изменений ключевых путей и зависимых объектов.


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

Для меня это сработало (пример кода):

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

    if ([keyPath isEqualToString:@"pageIndex"]) {

        // basically remove the observer from the fault object and assign the new
        if([object isFault]) {
            [object removeObserver:self forKeyPath:@"pageIndex"];
            [the_current_instance_returned_by_core_data addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionOld context:NULL];
        } 

        // do whatever you want to do on change...

    }
}
person hfossli    schedule 20.05.2011