I want to provide custom sorting using NSFetchedResultsController and NSSortDescriptor.
As a custom sort through the message NSSortDescriptor - (id) initWithKey: ascending: selector: impossible (see here ), I tried to use the derived class NSSortDescriptor to override the message compareObject: toObject :.
My problem is that the compareObject: toObject: method is not always called. It seems that it is only called when the data is already in memory. There is some optimization that uses database-based sorting instead of compareObject: toObject when data is retrieved from storage for the first time. (see here ).
My question is: how to get NSFetchedResultscontroller to use compareObject: toObject: message to sort data? (and whether it will work with a large data set)
One solution is to use binary storage instead of sqlite storage, but I don't want to do this.
Another solution:
-call executeFetch to sort data through SQL (compareObject is not called)
-make data changes and undo it.
-call executeFetch again (compareObject method is called)
It works in my case, but itβs a hack, and Iβm not sure that it will always work (especially with a large data set (larger than the lot size)).
UPDATED: You can play a sample sample of CoreDataBooks.
In RootViewController.m add this ugly hack:
- (void)viewWillAppear:(BOOL)animated { Book* book = (Book *)[NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:[self fetchedResultsController].managedObjectContext]; [[self fetchedResultsController] performFetch:nil]; [[self fetchedResultsController].managedObjectContext deleteObject:book]; [self.tableView reloadData]; }
In RootViewController.m, replace the sort descriptor code with:
MySortDescriptor *myDescriptor = [[MySortDescriptor alloc] init]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:myDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors];
Add class MySortDescriptor:
@implementation MySortDescriptor -(id)init { if (self = [super initWithKey:@"title" ascending:YES selector:@selector(compare:)]) { } return self; } - (NSComparisonResult)compareObject:(id)object1 toObject:(id)object2 { //set a breakpoint here return [[object1 valueForKey:@"author" ] localizedCaseInsensitiveCompare:[object2 valueForKey:@"author" ] ]; } //various overrides inspired by [this blog post][3] - (id)copy { return [self copyWithZone:nil ]; } - (id)mutableCopy { return [self copyWithZone:nil ]; } - (id)mutableCopyWithZone:(NSZone *)zone { return [self copyWithZone:zone ]; } - (id)copyWithZone:(NSZone*)zone { return [[MySortDescriptor alloc] initWithKey:[self key] ascending:[self ascending] selector:[self selector]]; } - (id)reversedSortDescriptor { return [[[MySortDescriptor alloc] initWithKey:[self key] ascending:![self ascending] selector:[self selector]] autorelease]; } @end
iphone core-data nsfetchedresultscontroller nssortdescriptor
FKDev
source share