如何将NSTreeController,NSOutlineView和Core Data与“隐形”根项一起使用?

时间:2009-11-05 06:06:10

标签: cocoa macos core-data nsoutlineview nstreecontroller

我有一个Core Data模型,它由一个特定实体的简单树组成,它有两个关系parentchildren。我有NSTreeController管理模型,NSOutlineView绑定到NSTreeController

我的问题是我需要一个根对象,但是这不应该显示在大纲视图中,只有它的子项应该显示在大纲视图的顶层。如果我将Interface Builder中NSTreeController的fetch谓词设置为parent == nil,那么一切正常,除了根项目在大纲视图中作为顶级项目可见。

我的实体有一个属性isRootItem,仅对根项有效。

我的模型看起来像这样:

Node 1
|
+-Node 2
  |   |
  |   +-Node 5
  |
  Node 3
  |
  Node 4

大纲视图应如下所示:

Outline View Image
(来源:menumachine.com

我需要在大纲视图的顶层显示节点2,3和4(节点1不应该是可见的),但是它们的父节点仍然是“节点1”。节点1的YES值为isRootItem,其他所有值均为NO

如果我将树控制器的fetch谓词设置为parent.isRootItem == 1,则会正确显示树,但是只要我将新项添加到顶层,它就会失败,因为树控制器没有分配“不可见的“根项目作为新项目的父项。

有没有办法让NSTreeController / NSOutlineView组合在这种情况下工作?

2 个答案:

答案 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];
}

答案 1 :(得分:0)

您是否尝试过绑定到NSTreeController的addChild:方法?

因为有这样的时间我不使用NSTreeController。

您可以取消它并实现Source视图的委托方法,这将使您更好地控制您显示的内容。它不是太多额外的工作,可能比敲打你试图让NSTreeController以你想要的方式工作更容易。