Основные данные, заполняющие обязательную связь из вновь созданного NSManagedObject

#objective-c #core-data #model-view-controller #nsoutlineview #nstreecontroller

#objective-c #основные данные #модель-представление-контроллер #nsoutlineview #nstreecontroller

Вопрос:

Это должно быть легко, насколько сложно это может быть.

У меня есть приложение core data на основе документов с очень простой моделью данных.

У меня есть объект «node» с отношением родительских / дочерних элементов к самому себе, контролируемый NSTreeController и просматриваемый через NSOutlineView. «Узел» также имеет необязательное (для одного) отношение к другому объекту типа «nodeProperties», который управляется NSArrayController. У меня есть подуровни NSManagedObject для обоих объектов. Мой класс document имеет выходы, привязанные как к экземплярам контроллера дерева, так и к экземплярам контроллера массива.

Моя проблема заключается в том, как гарантировать, что при создании нового «узла» действием пользовательского интерфейса в представлении схемы заполняется его связь с подходящим (уже существующим) объектом nodeProperties.

Подходы, которые я пробовал / рассматривал:

  1. Пусть контроллер дерева создаст «узел» (из его add:, addChild: actions) и заполнит связь с объектом nodeProperties в методе awakeFromInsert подкласса «узел». Проблема в том, что я не могу найти способ доступа к любому объекту nodeProperties из awakeFromInsert «узла». «Соответствующий» объект nodeProperties доступен из метода в классе document, но доступ к объекту document из метода node awakeFromInsert, похоже, нарушает принципы MVC, и я прочитал, что общий объект document не всегда безопасен при перетаскивании (что в моем случае также создаетновый объект узла)
  2. Напишите методы add: и addChild: action в классе document и вызывайте их из действий конечного пользователя вместо контроллера дерева (моя поддержка перетаскивания также есть в классе document). Затем из этих методов вызывают методы add: и addChild: в контроллере дерева, затем устанавливают связь nodeProperties для вновь созданного узла. Проблема в том, что я не знаю, как попросить контроллер дерева дать мне ссылку на вновь созданный узел? Я попытался использовать метод selectedObjects для получения родительского элемента, а затем сравнить дочерние элементы родителей до и после добавления, чтобы получить новый узел. Но содержимое дочерних элементов в данный момент не изменяется — возможно, это отложенное обновление?
  3. В качестве варианта 2, вообще не используйте контроллер дерева add:/ addChild: методы, а вместо этого создайте объект сущности узла в документе add:/ addChild: методы, используя контроллеры дерева selectedojets для получения родительского объекта. Мне это не очень нравится, поскольку кажется, что я делаю что-то за контроллерами дерева, и мне пришлось бы setContent: каждый раз, когда я создавал корневые объекты.
  4. Я рассматривал возможность наблюдения за созданием вновь созданного узла, но я не знаю, что нужно наблюдать, чтобы достичь этого.

Кто-то, должно быть, делал что-то подобное раньше, но я тралил безрезультатно. Любая помощь, советы, рекомендации будут очень приветствоваться.

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

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, а затем точно указать контроллеру дерева, куда в дереве вы хотите его вставить.