2009-11-05 1 views
3

У меня есть модель Core Data, которая состоит из простого дерева конкретной сущности, которая имеет два отношения: parent и children. У меня есть NSTreeController, управляющий моделью, с NSOutlineView, связанным с NSTreeController.Как использовать NSTreeController, NSOutlineView и Core Data с «невидимым» корневым элементом?

Моя проблема в том, что мне нужен один корневой объект, но это не должно отображаться в виде контура, только его дети должны отображаться на верхнем уровне структуры. Если я устанавливаю предикат выборки из NSTreeController в Interface Builder в parent == nil, все работает отлично, за исключением того, что корневой элемент отображается как элемент верхнего уровня в виде контура.

У моего объекта есть атрибут, isRootItem, что верно только для корневого элемента.

Моя модель выглядит следующим образом:

вид
Node 1 
| 
+-Node 2 
    | | 
    | +-Node 5 
    | 
    Node 3 
    | 
    Node 4 

Схема должна выглядеть следующим образом:

Outline View Image http://menumachine.com/quickies/nodes.png

Мне нужно отобразить узлы 2, 3 и 4 на верхнем уровне (Node 1 не должен быть видимым), но все же у их родителя есть «Node 1». Узел 1 имеет значение YES для isRootItem, а все остальные имеют NO.

Если я установил предикат выборки древовидного контроллера на parent.isRootItem == 1, это отобразит дерево правильно, но как только я добавлю новый элемент на верхний уровень, он терпит неудачу, потому что древовидный контроллер не назначает «невидимый» корень в качестве родительского элемента нового элемента.

Есть ли способ получить комбинацию NSTreeController/NSOutlineView, чтобы работать в этой ситуации?

+0

Вы можете написать предикат просто как 'parent.isRootItem' без проверки. – Abizern

+0

Спасибо, ты прав. –

ответ

2

Что я сделал, это подклассификация NSTreeController и переопределение -insertObject:atArrangedObjectIndexPath:, чтобы прямо установить родительский объект в мой корневой объект, если вставленный объект вставлен на верхний уровень дерева. Это, похоже, работает надежно.

Очевидно, потребуется больше работы для обработки перемещаемых элементов и вставки нескольких элементов, но это, по-видимому, лучший способ продвижения вперед.

- (void)insertObject:(id)object atArrangedObjectIndexPath:(NSIndexPath *)indexPath 
{ 
    NodeObject* item = (NodeObject*)object; 
    //only add the parent if this item is at the top level of the tree in the outline view 
    if([indexPath length] == 1) 
    { 
     //fetch the root item 
     NSEntityDescription* entity = [NSEntityDescription entityForName:@"NodeObject" inManagedObjectContext:[self managedObjectContext]]; 
     NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init]; //I'm using GC so this is not a leak 
     [fetchRequest setEntity:entity]; 
     NSPredicate* predicate = [NSPredicate predicateWithFormat:@"isRootItem == 1"]; 
     [fetchRequest setPredicate:predicate]; 

     NSError* error; 
     NSArray* managedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error]; 

     if(!managedObjects) 
     { 
      [NSException raise:@"MyException" format:@"Error occurred during fetch: %@",error]; 
     } 

     NodeObject* rootItem = nil; 
     if([managedObjects count]) 
     { 
      rootItem = [managedObjects objectAtIndex:0]; 
     } 
     //set the item's parent to be the root item 
     item.parent = rootItem; 
    } 
    [super insertObject:object atArrangedObjectIndexPath:indexPath]; 
    //this method just sorts the child objects in the tree so they maintain their order 
    [self updateSortOrderOfModelObjects]; 
} 
0

Вы пытались привязать к методу NSTreeController addChild:?

Это из-за таких времен, что я не использую NSTreeController.

Вы можете покончить с этим и реализовать методы делегата в представлении «Источник», что даст вам гораздо лучший контроль над тем, что вы показываете. Это не слишком много дополнительной работы и может быть проще, чем ударить головой, пытаясь заставить NSTreeController работать так, как вы этого хотите.

+0

Это работает для создания дочерних узлов существующих узлов. Например, если я выбрал «Node 2» и назвал «-addChild:», тогда ребенок будет правильно создан. Однако то, что я не могу сделать, это создать новые узлы на том же уровне, что и Узел 2. Если я вызываю «-add:», создается новый узел, но его родительский элемент равен нулю, а не моему корневому элементу «Узел 1». –

+0

Если я не могу заставить NSTreeController работать так, как мне нужно, я обязательно вернусь к методам представления данных/делегирования NSOutlineView, но NSTreeController так близок к работе, что я хочу сначала попробовать этот путь. –

+0

Будет интересно посмотреть, какие другие ответы вы получите. Я знаю, что вы имеете в виду в NSTreeController - иногда кажется, что он почти там ... – Abizern

Смежные вопросы