NSTreeController Grouping Nodes - Grouping At All
NSTreeController Grouping Nodes - Grouping At All
- Subject: NSTreeController Grouping Nodes - Grouping At All
- From: Arved von Brasch <email@hidden>
- Date: Fri, 12 May 2006 00:16:42 +1000
Hello Cocoa Dev List,
Since my last attempt, I've tried several different methods of
getting an NSOutlineView to work with CoreData and bindings, and I'm
about to give up and return to pure target / action datasource
methods. My main trouble stems around grouping. I can add and
delete leaf nodes easily regardless of whether I'm using an
NSTreeController, or faking it with an NSArrayController.
As before, I have two CoreData entities as the base of my
NSOutlineView: AritcleGroup and Article. ArticleGroup has attributes
title, author and rating, which are the three OutlineView column
headings. It also has an attribute leaf, and relationships parent
and children. Parent is to-one, and children is to-many, both are
optional. Article inherits from ArticleGroup and adds the attribute
filename which is a path to a the actual PDF or HTML article.
I only want 2 levels in my OutlineView. Articles should be able to
appear at the top level or as one of the children of an
ArticleGroup. ArticleGroups should only be able to appear at the top
level. This is why Articles inherit from ArticleGroup, so they can
just as happily be at the top level.
The behaviour I want is for the user to be able to select several top
level articles and then click a group button. This should result in
an ArticleGroup being created with its children being the previously
selected Articles.
I couldn't get this working with an NSTreeController at all, and as I
also needed to be able to filter my results, I've been working with
NSArrayControllers instead, but I'm still running into problems.
My grouping code looks like this:
IBOutlet NSArrayController *articles; // Array Controller bound to
my managedObjectContxt with a predicate of parent == nil.
IBOutlet NSOutlineView *articlesTable; //The OutlineView
- (NSArray *)selectedObjects {
NSIndexSet *selection = [articlesTable selectedRowIndexes];
if ([selection count] == 0) {
return [NSArray array];
}
NSMutableArray *selectedObjects = [NSMutableArray array];
int index = [selection firstIndex];
while (index <= [selection lastIndex]) {
[selectedObjects addObject: [articlesTable itemAtRow: index]];
index = [selection indexGreaterThanIndex: index];
}
return selectedObjects;
}
- (IBAction)group: (id)sender {
NSArray *selectedObjects = [self selectedObjects];
NSArray *allGroups = [selectedObjects filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat: @"leaf == 0"]];
NSArray *articlesNotInGroups = [selectedObjects
filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"leaf
== 1 AND parent == nil"]];
if ([allGroups count] == 0 && [articlesNotInGroups count] ==
[selectedObjects count]) {
// Group creation
NSManagedObject *group = [NSEntityDescription
insertNewObjectForEntityForName: @"ArticleGroup"
inManagedObjectContext: [articles managedObjectContext]];
[ articles addObject: group];
[articles removeObjects: selectedObjects];
[selectedObjects setValue: group forKey: @"parent"];
NSLog(@"Children: %d", [[group valueForKey: @"children"] count]);
}
// Code cut with logic dealing with selections that include an
ArticleGroup
[articlesTable reloadData];
}
The NSLog reports that the children have been successfully added to
the group, but by the time the data is reloaded, the articles
themselves have been deleted from my data store. Saving before
grouping and after grouping, inspecting the XML file each time
confirms this. I can't imagine where I'm possibly deleting them
here, except with the removeObjects: call, but removing that line
causes run time bugs claiming that Article isEqualToString: and
Article compare: aren't supported. This suggests to me a problem
with the sorting method in NSArrayController. Can I not have an
inherited object working like this? Am I simply doing something
(subtly) wrong? I have implemented all the DataSource methods for
NSOutlineView, and they are all pretty straightforward, the most
complex being:
- (id)outlineView: (NSOutlineView *)ov child: (int)index ofItem: (id)
item {
if (item == nil) {
return [[articles arrangedObjects] objectAtIndex: index];
}
NSArrayController *subArticles = [[[NSArrayController alloc]
initWithContent: [[item valueForKey: @"children"] allObjects]]
autorelease];
[subArticles setManagedObjectContext: [articles managedObjectContext]];
[subArticles setSortDescriptors: [articles sortDescriptors]];
[subArticles setFetchPredicate: [articles fetchPredicate]];
[subArticles rearrangeObjects];
return [[subArticles arrangedObjects] objectAtIndex: index];
}
and the simplest being:
- (int)outlineView: (NSOutlineView *)ov numberOfChildrenOfItem: (id)
item {
if (item == nil) {
return [[stories arrangedObjects] count];
}
return [[item valueForKey: @"children"] count];
}
Any insight is greatly appreciated.
Cheers,
Arved
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden