Наблюдаемый объект не зарегистрирован как наблюдатель

#objective-c #core-data #cocoa-bindings #nsmanagedobject #nsarraycontroller

#objective-c #core-данные #cocoa-привязки #nsmanagedobject #nsarraycontroller

Вопрос:

У меня возникла проблема, когда мой контроллер массива обновляется новыми данными, полученными из запроса сервера.

Настройка

У меня есть объект entity (назовем его MyParent ), который обладает несколькими свойствами:

имя 
возраст 
описание 
widgetID

И объект entity (назовем его MyWidget), который имеет несколько свойств:

имя 
размер 
описание

Размер является строковым представлением NSSize объекта. Это упрощает хранение и извлечение из основного хранилища данных, а также на сервер и обратно в формате JSON. Чтобы представить размер в пользовательском интерфейсе, я выделил подкласс MyWidget и предоставил пользовательский параметр установки и получения в качестве категории пользовательского класса (я сделал это, чтобы Xcode не перезаписывал мои изменения, если мне нужно внести изменения в модель):

 -(void)setObjectWidth:(NSInteger)aValue {
    [self setObjectSize:NSMakeSize(aValue, [self objectHeight])];
}

-(void)setObjectHeight:(NSInteger)aValue {
    [self setObjectSize:NSMakeSize([self objectWidth], aValue)];
}

-(void)setObjectSize:(NSSize)aValue {
    [self setSize:NSStringFromSize(aValue)];
}

-(NSInteger)objectWidth {
    return [self objectSize].width;
}

-(NSInteger)objectHeight {
    return [self objectSize].height;
}

-(NSSize)objectSize {
    return NSSizeFromString([self size]);
}
  

Я получаю widget , выполняя поиск в widgetId методе как категория в родительском:

 -(MyWidget *)widget {
    NSManagedObjectContext * moc = [[NSApp delegate] managedObjectContext];

    return [moc fetchObjectForEntityName:@"MyWidget"
                                 withUID:[self widgetID]];
}
  

fetchObjectForEntityName:withUID является категорией в контексте управляемого объекта.

В пользовательском интерфейсе у меня есть контроллер массива, привязанный к TableView MyParent объектов. При выборе объекта в пользовательском интерфейсе отображаются сведения, привязанные к соответствующим значениям:

parentArrayController --> parentArray (управляемые объекты в массиве)
Родительская таблица --> parentArrayController.arrangedObjects.name

uiWidthTextField --> parentArrayController.selection.widget.objectWidth 
uiHeightTextField --> parentArrayController.selection.widget.objectHeight

Контроллер массива отслеживается на предмет изменений, чтобы он мог отправлять уведомления для других частей приложения, которым необходимо знать, что выбранный объект изменен

Что работает

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

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

Что сломано

Когда список возвращается, он анализируется правильно, но приложение выдает жалобы при обновлении контроллера массива:

Серьезная ошибка приложения. Во время обработки изменений Core Data было обнаружено исключение: не удается удалить наблюдателя для ключевого пути «widget.objecttheight», поскольку он не зарегистрирован как наблюдатель. с помощью userInfo (null)

Не удается удалить наблюдателя для ключевого пути «widget.objecttheight» из, потому что он не зарегистрирован как наблюдатель.

Что я пробовал

Я пытался добавить функцию willChangeValueForKey: и сделал это, обернув ее вокруг параметра Objecttheight и objectWidth, но, похоже, это не дает возможности обратиться за помощью.

Я полагаю, проблема в том, что IB привязан к widget.objectHeight , а widget — это поиск по родительскому объекту, в отличие от истинного свойства KVO / KVC. Однако мне не нужен установщик на widget (хотя я попробую это в следующий раз).

Я знаю, что чего-то не хватает, но не могу указать пальцем, что именно.

Просьба

Любая помощь в решении этой проблемы была бы очень признательна!

Ответ №1:

Вам нужно установить objectWidth и objectHeight как немоделированные свойства MyWidget. У вас возникают проблемы с KVO, потому что objectWidth и objectHeight не являются ключами MyWidget, а просто имеют имена методов в форме getters и setters.

Просто добавьте:

 @property() NSInteger objectWidth;
@property() NSInteger objectHeight;
  

к классу MyWidget, и это должно предоставить ключи для работы KVO. (Возможно, потребуется дважды проверить мою форму собственности. Прошло некоторое время, и мне пришлось написать свойство integer.)

Комментарии:

1. спасибо за ответ. Я попытался добавить свойство @ в модель, но это ничего не изменило. Затем я обернул каждый установщик / получатель соответствующим значением willChangeValue, а также значением willAccessValue . Никакой радости. Затем я переместил их из категории непосредственно в объект модели. По-прежнему безуспешно : — ( Насколько я могу судить, это сбой, как вы указали. И это имеет смысл. Я также попытался отключить автоматическое уведомление с помощью automaticallyNotifiesObserversForKey и вернуть NO для этих ключей (Objecttheight и т.д.). Мягко говоря, неприятно!

2. наконец-то вернулся к закрытию моих открытых проблем. Ваше решение сработало. Я не осознавал, что я настроил установщики и получатели так, чтобы они не выполняли автоматическое уведомление, и поэтому синтезированные установщик и получатели не запускали уведомления KVC. Быстрое исправление, и все работало просто отлично. Спасибо!