NSFetchedResultsController and getting the grouping right

廉价感情. 提交于 2020-01-25 22:52:49

问题


I have the following problem. I have a UITableview that is powered by an NSFetchedResultsController. It should display let's say a projects, folders and files. There is no bigger hierarchy than that. So a project has several folders and those have several files. Now my table view should display those files, grouped by folders.

So i thought my fetch requests' predicate would simply be:

[NSPredicate predicateWithFormat:@"folder.project = %@", self.project];

I would then use MagicalRecord to make an NSFetchedResultsController by making something like this:

[File fetchAllGroupedBy:@"folder.name"
          withPredicate:sectionPredicate
               sortedBy:@"folder.name"
              ascending:YES];

This basically works with one big problem... if there is no file in the folder, I wouldn't get a section for that folder (which I need!!!!)

So what I need is the tableview to also display section headers for empty folders:

Folder A
  File 1
  File 2
Folder B
Folder C
  File 3

I could do it without the NSFetchedResultsController, but I love that it handles the inserting/deleting of rows and sections so nice and that it observes for changes...

Thx for helping, Cheers, Georg


回答1:


The solution is indeed a bit complex. I will try and explain a partial solution (no nested folders, and not section sort order support)

Model changes:
1) set the parent entity of Folder to File (not necessary if you use a dummy item).
2) add the BOOL field isFinal to File entity.
3) generate the class files for the entities.
4) in Folder.h implement -awakeFromInsert like this:

- (void) awakeFromInsert
{
    self.isFinal = YES;
    self.folder = self;//You could also fabricate a dummy item
}

FetchedResultsController:
1) set your fetch request like so:

NSFetchRequest* request = [[NSFetchRequest alloc] initWithEntityName:@"File"];
NSSortDescriptor* terminalSort = [NSSortDescriptor sortDescriptorWithKey:@"isFinal" ascending:YES];
NSSortDescriptor* nameSort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
[request setSortDescriptors:@[terminalSort,nameSort]];
[request setPredicate:[NSPredicate predicateWithFormat:@"folder.project == %@",project]]
//Any additional settings

2) initialise your FRC like so :

self.fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:self.managedObjectContext
                                      sectionNameKeyPath:@"folder"//or @"folder.<some unique property>"
                                               cacheName:nil];

notice that the sectionNameKeyPath is set to folder, and not folder.name to support folders with the same name (if this is not required, and folder name is unique, use folder.name )

3) in your -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: add at the beginning of the method:

File* file = (File*)anObject;
if (file.isFinal) {
    return;
}

Table view:
1) implement:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
    return [sectionInfo numberOfObjects] - 1;
}

2) implement:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    id<NSFetchedResultsSectionInfo> sec = [self.fetchedResultsController sections][section];

    return [[[[sec objects] objectAtIndex:0] folder] name];
}

This should give you the basic functionality you need. To support a more complex behaviour, additional changes will be required.



来源:https://stackoverflow.com/questions/16064051/nsfetchedresultscontroller-and-getting-the-grouping-right

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!