#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. Быстрое исправление, и все работало просто отлично. Спасибо!