I like controlling it with the FRC, and leave the delegate calls to change it if they want different/custom functionality. I also believe that the FRC should generally be constructed as a class method on the entity being observed.
You can make the formatted string be a full-on attribute of the object, but that seems wasteful.
You could also make it be a true transient attribute. That may be more proper, but I was using an existing model, and didn't want to change the model. Since that project, I have just kept with this methodology for any other similar cases.
Anyway, this example is almost taken straight from an existing app. I had to change some things, so I hope I didn't leave out anything.
Create the fetch request used by your FRC, so that it sorts based on the date
property of the object. This allows normal core data fetching on a standard property.
+ (NSFetchedResultsController *)
fetchedResultsController:(NSManagedObjectContext *)context
{
NSFetchRequest* request = [NSFetchRequest
fetchRequestWithEntityName:[self entityName]];
request.sortDescriptors = @[[NSSortDescriptor
sortDescriptorWithKey:@"date"
ascending:YES]];
request.fetchBatchSize = 30;
request.returnsObjectsAsFaults = NO;
NSString *cacheName = [[self entityName]
stringByAppendingString:@"-all-bydate"];
return [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:@"dateAsSectionName"
cacheName:cacheName];
}
Add an instance variable to your subclass... you will manage it yourself...
@implementation MyManagedObjectSubclass {
NSString *dateAsSectionName_;
}
Add an accessor method. We only create the formatter once. Change it to your own liking.
- (NSString*)dateAsSectionName
{
static NSDateFormatter *dateFormatter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"EEE, MMM d, h:mm a";
dateFormatter.dateFormat = @"EEEE MMMM d";
});
if (dateAsSectionName_ == nil) {
NSDate *date = [self primitiveDate];
dateAsSectionName_ = [dateFormatter stringFromDate:date];
}
return dateAsSectionName_;
}
Clear out our section name when the date changes, so we will re-compute its value the next time the accessor is called.
- (void)setDate:(NSDate*)date
{
if ([[self primitiveDate] isEqualToDate:date]) return;
[self willChangeValueForKey:@"date"];
[self setPrimitiveDate:date];
[self didChangeValueForKey:@"date"];
dateAsSectionName_ = nil;
}
Tell KVO that dateAsSectionName
depends on date
.
+ (NSSet *)keyPathsForValuesAffectingDateAsSectionName
{
return [NSSet setWithObject:@"date"];
}