How to use NSTreeController, NSOutlineView and Core Data with an "invisible" root element?

I have a Core Data model, which consists of a simple tree of a specific entity, which has two relations, parentand children. I have a NSTreeControllermodel manager, but NSOutlineViewattached to NSTreeController.

My problem is that I need one root object, but it should not be displayed as a structure, only its children should be displayed at the top level of the structure view. If I set the select predicate NSTreeControllerin Interface NSTreeControllerin parent == nil, everything works fine, except that the root element is visible as a top-level element in the form of a structure.

My entity has an attribute isRootItemthat is true only for the root element.

My model looks like this:

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

The outline view should look like this:

Outline view image
(source: menumachine.com )

I need to display nodes 2, 3 and 4 at the top level of the schematic diagram (node ​​1 should not be visible), but their parent should be "Node 1". Node 1 matters YESto isRootItemand all the others have NO.

If I set the tree controller selection predicate to parent.isRootItem == 1, it displays the tree correctly, but as soon as I add a new element to the top level, it crashes because the tree controller does not designate the "invisible" root element as the parent of the new element.

NSTreeController/NSOutlineView ?

+3
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 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];
}
+2

NSTreeController addChild:?

- , NSTreeController.

"", , . , , NSTreeController , .

0

Source: https://habr.com/ru/post/1721950/


All Articles