I'm seeing an issue where the NSFetchedResultsController is only sorting by the first NSSortDescriptor
in the sortDescriptors
array when the data changes. It's really infuriating.
I'm using an NSFetchedResultsController to manage a tableview that is displaying a list of items. These items have an inherent order based on the number
property, but a user can favorite an item. Favorited items are displayed at the top of the table view, sorted by the number
property.
So, the model looks something like this:
@interface Thing : NSManagedObject
@property (nonatomic, retain) NSNumber *number;
@property (nonatomic, retain) NSNumber *favorite;
@end
@implementation Thing
@dynamic number;
@dynamic favorite;
@end
And I'm configuring my NSFetchedResultsController
like so:
- (void)loadView {
...
//
// configure fetched results controller for the things table view
NSFetchRequest *fetchThings = [[NSFetchRequest alloc] init];
fetchChannels.entity = [NSEntityDescription entityForName:NSStringFromClass([Thing class])
inManagedObjectContext:[DataManager sharedInstance].managedObjectContext];
fetchThings.sortDescriptors = @[
[NSSortDescriptor sortDescriptorWithKey:@"favorite" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:@"number" ascending:YES] ];
_fetchController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchThings
managedObjectContext:[DataManager sharedInstance].managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
NSError *error = nil;
if (![_fetchController performFetch:&error]) {
NSLog(@"error performing fetch! %@", error.localizedDescription);
}
}
When the table is initially loaded, _fetchController
correctly sorts the items, so you could end up with something like this:
- Thing: favorite = YES, number = 2
- Thing: favorite = YES, number = 3
- Thing: favorite = NO, number = 1
- Thing: favorite = NO, number = 4
But if you were to un-favorite Thing Number 2, it only sorts by the 1st sort descriptor, and the list looks like this:
- Thing: favorite = YES, number = 3
- Thing: favorite = NO, number = 2
- Thing: favorite = NO, number = 1
- Thing: favorite = NO, number = 4
Has anyone run into this issue or found a work around for it?
It would appear that if I favorite everything, then unfavorite everything, the sorting works itself out. This leads me to believe this could be a faulting issue? Unfortunately, I'm not sure how to work around that, either.
OK, I figured it out, and it's my own fault.
Just because the field represents a BOOL
doesn't mean it's actually a BOOL
. The favorite
field in the Thing
model is actually an NSNumber
, and as such, has 3 states, @(YES)
, @(NO)
, and nil
. Once I made sure I was initializing the favorite
field properly the sorting started working as expected again.