Reputation: 925
There are a lot of topics on core data tree structures but I'm left with some questions.
What I'm trying to create is a simple directory structure. (Folders with subfolders with subfolders, ... and later on also files.)
I now have this Folder entity:
And I'm adding folders like this: [Obviously this is dummy data and this will be dynamicly inserted later]
// root 1
Folder *root1 = [NSEntityDescription insertNewObjectForEntityForName:@"Folder" inManagedObjectContext:context];
root1.name = @"Root 1";
root1.parent = nil;
// folder 1 in root 1
Folder *subFolder1 = [NSEntityDescription insertNewObjectForEntityForName:@"Folder" inManagedObjectContext:context];
subFolder1.name = @"Folder 1 in root 1";
subFolder1.parent = root1;
root1.children = [NSSet setWithObjects: subFolder1, nil];
Now I want to make a ViewController for every folder and then open a new ViewController for every subfolder. (Or an infinite UITabelView)
When I loop in the Folder entity with this code:
NSArray *folders = [context executeFetchRequest:fetchRequest error:&error];
for(Folder *folder in folders){
NSLog(@"Profile: %@", folder.name);
}
I get all the folders at once.
So the question is: How can I log this out in a tree structure? So I can create a ViewController for all the root folders first, and then for every subfolder another ViewController etc. etc... (In other words: How can I read this entity as I would put it in a UITabelView)
Upvotes: 6
Views: 2088
Reputation: 70966
You don't detail how your fetch request is constructed, but the key is to use an NSPredicate
to filter the results only to include the Folder
objects of interest at any given time. To do this, you'll need to store a reference to the current parent folder in the view controller:
@property (readwrite, strong) Folder *parentFolder;
If you're at the root of the tree, this will be nil
, otherwise it will have a reference to the current folder whose contents you're displaying.
Then use this property in a predicate:
NSFetchRequest *fetchRequest = ...
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"parent = %@", self.parentFolder];
[fetchRequest setPredicate:predicate];
When you're at the root, this will select only instances of Folder
where parent
is nil
(i.e. only root level objects). At every other level, it selects only Folders
where parent
is whatever the current parent folder is.
As a side note, in your sample code, it's not necessary to set subFolder1.parent
and root1.children
. Core Data inverse relationship management means that you only need to do this on one side of the relationship. It doesn't hurt anything to do both (aside from a very minor performance hit), but it also serves no purpose.
Upvotes: 8