[英]How do I use NSTreeController, NSOutlineView and Core Data with an “invisible” root item?
I have a Core Data model which consists of a simple tree of a particular entity, which has two relationships, parent
and children
. 我有一个核心数据模型,它由一个特定实体的简单树组成,它有两个关系, parent
和children
。 I have an NSTreeController
managing the model, with an NSOutlineView
bound to the NSTreeController
. 我有一个管理模型的NSTreeController
, NSOutlineView
绑定到NSTreeController
。
My problem is that I need a single root object, but this should not display in the outline view, only its children should be displayed at the top level of the outline view. 我的问题是我需要一个根对象,但是这不应该显示在大纲视图中,只有它的子项应该显示在大纲视图的顶层。 If I set the fetch predicate of the NSTreeController
in Interface Builder to parent == nil
, everything works fine except the root item is visible as the top level item in the outline view. 如果我将Interface Builder中NSTreeController
的fetch谓词设置为parent == nil
,则一切正常,但根项目在大纲视图中作为顶级项目可见。
My entity has an attribute, isRootItem
, that is true for the root item only. 我的实体有一个属性isRootItem
,仅对根项有效。
My model looks like this: 我的模型看起来像这样:
Node 1
|
+-Node 2
| |
| +-Node 5
|
Node 3
|
Node 4
The outline view should look like this: 大纲视图应如下所示:
(source: menumachine.com ) (来源: menumachine.com )
I need to display Nodes 2, 3 and 4 at the top level of the outline view (Node 1 should not be visible), but still have their parent be "Node 1". 我需要在大纲视图的顶层显示节点2,3和4(节点1不应该是可见的),但是它们的父节点仍然是“节点1”。 Node 1 has a value of YES
for isRootItem
and all the others have NO
. 对于isRootItem
,节点1的值为YES
,而其他所有节点都为NO
。
If I set the fetch predicate of the tree controller to parent.isRootItem == 1
, this displays the tree correctly, but as soon as I add a new item to the top level it fails because the tree controller does not assign the "invisible" root item as the parent of the new item. 如果我将树控制器的fetch谓词设置为parent.isRootItem == 1
, parent.isRootItem == 1
正确显示树,但是一旦我将新项添加到顶层,它就会失败,因为树控制器没有指定“不可见”根项目作为新项目的父项。
Is there a way to get the NSTreeController
/ NSOutlineView
combination to work in this situation? 有没有办法让NSTreeController
/ NSOutlineView
组合在这种情况下工作?
What I've ended up doing is subclassing NSTreeController and overriding -insertObject:atArrangedObjectIndexPath:
to directly set the parent to my root object if the object being inserted is being inserted at the top level of the tree. 我最终做的是-insertObject:atArrangedObjectIndexPath:
NSTreeController并重写-insertObject:atArrangedObjectIndexPath:
如果正在插入的对象插入树的顶层,则直接将父对象设置为我的根对象。 This seems to work reliably. 这似乎可靠地工作。
Obviously more work would be needed to handle moving items and inserting multiple items but this seems to be the best way forward. 显然,处理移动物品和插入多个物品需要更多的工作,但这似乎是最好的前进方式。
- (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];
}
Have you tried binding to the NSTreeController's addChild:
method? 您是否尝试过绑定到NSTreeController的addChild:
方法?
It's because of times like this that I don't use NSTreeController. 因为这样的时候我不使用NSTreeController。
You could do away with it and implement the delegate methods of the Source view which will give you much better control about what you display. 您可以取消它并实现Source视图的委托方法,这将使您更好地控制您显示的内容。 It isn't too much extra work and might be easier than banging you head trying to get the NSTreeController to work how you want it to. 这不是太多额外的工作,可能比敲打你试图让NSTreeController以你想要的方式工作更容易。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.