iOS CoreData NSFetchedResultsController sections and sorting
I currently have a CoreData entity that has a name
and date
attributes, and I would like to create a NSFetchedResultsController
that returns the results sectioned by name
sorted by date
descending (both the sections and its contents), and if possible, only one entry per section. I prefer not to use NSDictionaryResultType
.
Lets say I have the following entries:
Name | Date (year/month/day)
-----+----------------------
Anne | 2014/01/16
John | 2014/01/17
John | 2014/01/15
Nick | 2014/01/13
Nick | 2014/01/10
For the above data I wish to obtain only the following results:
Section | Entry Date
--------+-----------
John | 2014/01/17
Anne | 2014/01/16
Nick | 2014/01/13
How do I create the NSFetchedResultsController
to obtain only the data and in the order listed above?
As of now I have the following code:
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:moc];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"my predicate" argumentArray:...]];
[fetchRequest setPredicate:predicate];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:@"name"
cacheName:nil];
The above code sections the data by name
, but each section doesn't have its entries sorted by date
AND it has entries that are not from that name
!
The result that I want is the table showing unique name
sorted by date
like showed in the beginning of the post.
Update: I've been unable to do this, so I switched to result type dictionary and used group by for now, I will leave the question open in the hopes someone knows how to do it.
There is no way (that I am aware of) to limit each section to one result in the NSFetchedResultsController.
But, you might not have to do this. You could probably get away with not displaying everything that is not in the first section.
Also, you should be aware that you should not section the request by using any other key than the key used in the primary sort descriptor
If you are using this with a tableView you could try something like this:
FRC creation
NSSortDescriptor *sdName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSSortDescriptor *sdDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
// sort by name, then sort by date
[fetchRequest setSortDescriptors:@[sdName, sdDate]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:@"name"
cacheName:nil];
// fetch...
and the tableViewDataSource:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSFetchedResultsController *fetchedResultsController = [self fetchedResultsController];
return [fetchedResultsController.sections count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1; // only display one result for each section
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSFetchedResultsController *fetchedResultsController = [self fetchedResultsController];
YourObject *object = [fetchedResultsController objectAtIndexPath:indexPath];
... configure cell ...
Depending on how many objects you have per person this might not be feasible. If there are a lot of entries you won't display I would recommend to normalize the core data model. Eg:
You then would display a list of Persons. But maybe this normalization would be a good idea regardless of the number of objects per name. Fetching more objects than are displayed smells fishy to me.
关于我的评论,这是一些代码片段
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"EntityThingO"];
NSSortDescriptor *sortDescriptorDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSSortDescriptor *sortDescriptorName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
fetchRequest.sortDescriptors = @[sortDescriptorDate , sortDescriptorName];
[fetchRequest setFetchBatchSize:10];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:@"date"
cacheName:nil];
链接地址: http://www.djcxy.com/p/6144.html