Как я могу создать интерфейс master-detail с Core Data и абстрактной сущностью? - PullRequest
2 голосов
/ 28 ноября 2009

У Apple есть симпатичное небольшое руководство по созданию простого интерфейса с мастер-деталями. Интерфейсный Разработчик даже автоматически сгенерирует один для вас из сущности Core Data. Однако я пытаюсь сделать что-то более сложное, чем простой пример, и некоторое время я пытался заставить его работать.

У меня есть приложение на основе документов Core Data. Модель включает в себя абстрактную сущность Page и несколько конкретных подразделов Page. Все страницы имеют общие атрибуты (например, «имя»), и они определены в странице. Очевидно, что субъекты имеют уникальные для них атрибуты.

Я хочу, чтобы интерфейс позволял пользователю видеть все типы страниц в основном списке (NSTableView). Когда они выбирают страницу, отображаемые поля сведений будут зависеть от типа страницы.

Вот что у меня сейчас есть:

У меня есть основной файл пера, где отображается основной список, а также все поля, общие для страницы. Есть перо для каждого типа страницы со своими конкретными полями. В главном файле пера есть основной NSArrayController, который заполняет NSTableView. В каждом из перьев, специфичных для страницы, есть NSArrayController, так что я могу связать поля сведений с атрибутами текущего выделения. Все мои NSArrayControllers настроены одинаково, и все они привязаны к одному и тому же managedObjectContext и одному и тому же selectionIndexes.

Я использую метод Аарона Хиллегаса для обмена мнениями, который он описывает в своей книге Какао. Поэтому я зарегистрировался для NSTableViewSelectionDidChangeNotifications, и когда я получаю его, он вызывает метод switchView:

switchView просматривает выбранный в данный момент объект, проверяет, какой это тип страницы, и заменяет соответствующий файл пера в соответствии с методом Хиллегаса.

Все работает нормально, если я только добавляю страницы одного типа, но как только я добавляю страницу второго типа, я получаю эту ошибку:

Ошибка установки значения для пути выбора ключа. Индексы объекта (из объекта привязанного объекта: Страница, количество выбранных объектов: 1): [valueForUndefinedKey:]: объект NoColPage не соответствует значению ключа, кодирующему для стороны ключа.

Последняя часть ошибки имеет смысл: она застревает, пытаясь отобразить неправильное перо, поэтому пытается привязать поля, которые не существуют для этого объекта.

Я добавил поле selectionIndexes в MyDocument, чтобы все мои NSArrayControllers могли связываться с одним и тем же местом. Я мучился из-за этого в течение нескольких дней, и я не могу понять это. Есть идеи?

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

PS: инструмент Interface Builder для генерации интерфейса master-detail из сущности Core Data не работает так, как я хочу, для абстрактных сущностей. Он только создает поля для атрибутов в суперобъекте.

Редактировать: Я думаю, что Джошуа что-то задумал, но, к сожалению, это не работает - я продолжаю сталкиваться с той же проблемой. Сначала мне было трудно, потому что я не понимал, что -unbind: ожидает строковую константу, а не ключевой путь.

Я пробовал несколько вариантов: где я отслеживаю отображаемый в данный момент контроллер массива пера; где я отслеживаю отображаемый в данный момент тип страницы и отменяю привязку / перепривязываю только когда пытаюсь отобразить другой тип страницы ...

Вот соответствующий раздел кода.

-(void) displayViewController: (ManagingVC *) vc withClass:(NSString*) className {

//Try to end editing
NSWindow *w = [box window];
BOOL ended = [w makeFirstResponder:w];
if (!ended) {
    NSBeep();
    return;
}

//The Managing View Controller's NSArrayController
NSArrayController* vcAc = [vc arrCont];

//if the page we're trying to switch to is NOT the same type as the current page we're displaying
//if it is, do nothing.
if (![currPageDisplayed isEqual:className]) {

    //unbind the old view controller
    ManagingVC *oldvc = [viewControllers objectForKey:className];
    NSArrayController* oldsac = [oldvc arrCont];
    [oldsac unbind:@"selectionIndexes"];

    //bind the new view controller
    [vcAc bind:@"selectionIndexes" toObject:self withKeyPath:@"selectionIndexes" options:nil];
    currPageDisplayed = className;

    NSView *v = [vc view];

    //display the new view in an NSBox in the main nib
    [box setContentView:v];
}

}

Ответы [ 2 ]

1 голос
/ 28 ноября 2009

Проблема в том, что вы оставляете контроллеры массива ваших перьев привязанными к выделенному документу, что заставляет их пытаться (когда выбор изменяется) представлять выбранный элемент.

Попробуйте это:

  1. Снимите крепления в наконечниках.
  2. Перед добавлением нового представления подключите его привязки в коде.
  3. Перед удалением старого представления отключите его привязки в коде.

Это должно сделать все счастливым.

0 голосов
/ 03 декабря 2009

Потратив слишком много времени, пытаясь синхронизировать каждый контроллер массива NIB, я отказался от этого подхода. Единственное, что сработало для меня, - это программный контроль того, какие элементы графического интерфейса отображаются в главном кончике и их привязки. Это означает устранение других перьев. Это не совсем устойчивое решение, если вы работаете с несколькими текстовыми полями, но сейчас оно работает для меня.

Я все еще следую совету Джошуа, чтобы отменить привязку перед переключением представления, но сейчас я только связываю текстовые поля с arrayController.selection.whwhatKey

...