#objective-c #core-data #model-view-controller #nsoutlineview #nstreecontroller
#objective-c #основные данные #модель-представление-контроллер #nsoutlineview #nstreecontroller
Вопрос:
Это должно быть легко, насколько сложно это может быть.
У меня есть приложение core data на основе документов с очень простой моделью данных.
У меня есть объект «node» с отношением родительских / дочерних элементов к самому себе, контролируемый NSTreeController и просматриваемый через NSOutlineView. «Узел» также имеет необязательное (для одного) отношение к другому объекту типа «nodeProperties», который управляется NSArrayController. У меня есть подуровни NSManagedObject для обоих объектов. Мой класс document имеет выходы, привязанные как к экземплярам контроллера дерева, так и к экземплярам контроллера массива.
Моя проблема заключается в том, как гарантировать, что при создании нового «узла» действием пользовательского интерфейса в представлении схемы заполняется его связь с подходящим (уже существующим) объектом nodeProperties.
Подходы, которые я пробовал / рассматривал:
- Пусть контроллер дерева создаст «узел» (из его add:, addChild: actions) и заполнит связь с объектом nodeProperties в методе awakeFromInsert подкласса «узел». Проблема в том, что я не могу найти способ доступа к любому объекту nodeProperties из awakeFromInsert «узла». «Соответствующий» объект nodeProperties доступен из метода в классе document, но доступ к объекту document из метода node awakeFromInsert, похоже, нарушает принципы MVC, и я прочитал, что общий объект document не всегда безопасен при перетаскивании (что в моем случае также создаетновый объект узла)
- Напишите методы add: и addChild: action в классе document и вызывайте их из действий конечного пользователя вместо контроллера дерева (моя поддержка перетаскивания также есть в классе document). Затем из этих методов вызывают методы add: и addChild: в контроллере дерева, затем устанавливают связь nodeProperties для вновь созданного узла. Проблема в том, что я не знаю, как попросить контроллер дерева дать мне ссылку на вновь созданный узел? Я попытался использовать метод selectedObjects для получения родительского элемента, а затем сравнить дочерние элементы родителей до и после добавления, чтобы получить новый узел. Но содержимое дочерних элементов в данный момент не изменяется — возможно, это отложенное обновление?
- В качестве варианта 2, вообще не используйте контроллер дерева add:/ addChild: методы, а вместо этого создайте объект сущности узла в документе add:/ addChild: методы, используя контроллеры дерева selectedojets для получения родительского объекта. Мне это не очень нравится, поскольку кажется, что я делаю что-то за контроллерами дерева, и мне пришлось бы setContent: каждый раз, когда я создавал корневые объекты.
- Я рассматривал возможность наблюдения за созданием вновь созданного узла, но я не знаю, что нужно наблюдать, чтобы достичь этого.
Кто-то, должно быть, делал что-то подобное раньше, но я тралил безрезультатно. Любая помощь, советы, рекомендации будут очень приветствоваться.
Комментарии:
1. Re: 2 —
InsertChild
похоже, запланировано в цикле выполнения с некоторым эквивалентомdispatch_async
. Вы могли бы попробовать использоватьdispatch_async
для последующего запуска блока вашего собственного кодаinsertChild
.2. Однако, я думаю, я бы предпочел переопределить метод, который обновляет childrenKeyPath для родительского элемента, чтобы «наблюдать» за изменениями в дочернем наборе и реагировать на добавление туда новых дочерних элементов.
Ответ №1:
Итак, после долгих поисков и экспериментов ответом был вариант 3. Документ создает новый узел, заполняющий его обязательную связь, в методах add и addChild action, а затем вставляет узел в контроллер дерева, используя метод
NSTreeController insertObject:atArrangedObjectIndexPath:
Для тех, кому интересно, это мой метод addChild в классе document . В нем есть несколько особенностей из моей модели данных
- (IBAction)addChildAction:(id)sender
{
NSArray *indexPaths = [nodeTreeController selectionIndexPaths];
NSArray *selectedObjects = [nodeTreeController selectedObjects];
for (NSUInteger i = 0; i < [indexPaths count]; i )
{
QVXpandNode *parentNode = [selectedObjects objectAtIndex:i];
if ((parentNode) amp;amp; ([parentNode.isMaster boolValue])) // can only add nodes under the master node
{
QVXpandNode *createdNode = [self createPopulatedNode];
// Dont belelieve below is safe when >1 selected,
// since adding a new node will result in the tree paths changing?
// Hmmm but I do want to support multiple selection addition??
[nodeTreeController
insertObject:createdNode
atArrangedObjectIndexPath:[[indexPaths
objectAtIndex:i] indexPathByAddingIndex:[parentNode.children count]]];
}
}
}
Вы увидите, что я не уверен, буду ли я размещать вторые и более поздние дочерние элементы по правильному пути, если перед вызовом действия было выбрано> 1 строк.
Метод addSibling немного сложнее из-за необходимости вычисления последнего значения пути индекса, но в остальном аналогичен. Я могу воспроизвести его, если кто-нибудь захочет его увидеть, но ключ к заполнению обязательного отношения в новом узле дерева — это сделать это в классе document, а затем точно указать контроллеру дерева, куда в дереве вы хотите его вставить.