КВО задача "Невозможно удалить наблюдателя" - PullRequest
1 голос
/ 28 июля 2010

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

Невозможно удалить наблюдателя для ключевого пути «career.type» из Object, вероятнее всего из-за значения для ключа «career»изменилось без отправки соответствующего уведомления 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 и заново установить ее с установленным значением nil и соответствующим образом для поля?

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

1 Ответ

4 голосов
/ 20 мая 2011

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

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

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

Хотя значения не изменяются семантически по сравнению с вашимВ перспективе буквальные байты в памяти меняются по мере материализации объекта.Механизм наблюдения значения ключа требует, чтобы Базовые Данные выдавали уведомление всякий раз, когда значения изменяются, как это рассматривается с точки зрения сравнения указателей.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...

    }
}
...