date sorting core data NSFetchedResultsController
The program I am working on is a modified version of "CoreDataBooks", taken from Apple iPhone sample code. In "CoreDataBooks" there is a list of authors, some of whom have multiple books. A navigation controller is set up, with the sections divided up by author name. In each section, there is a list of books for each author.
So I took this code and am trying to make a list of names, arranged by section. My entity is called "Patient". Each entity has attributes myDate and myName, as well as a few others. I want to arrange sections by myDate, with a list of names in each section, all of which have the same date.
I am having difficulty with the NSFetchedResultsController method. When the dates are created using a date picker, they all have a timestamp. This timestamp makes them different, and they will be placed into separate sections if you sort by myDate in the sectionNameKeyPath method.
I did fairly extensive searching online, and came up with the solution below. You create another transient attribute, an NSString, and then use it to sort the sections. This is done by creating a date formatter, which is shown below. I include my setter for my NSString, as well as the NSFetchedResultsController method.
Any help will be greatly appreciated.
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
PatientsAppDelegate*appDelegate=[[UIApplication sharedApplication]delegate];
NSManagedObjectContext*managedObjectContext=appDelegate.managedObjectContext;
// Create and configure a fetch request with the Book entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Patient" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Create the sort descriptors array.
NSSortDescriptor *dateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myDate" ascending:YES];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:dateDescriptor, nameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// NSLog(@"%@",myFormattedDate);
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"transactionDay"
cacheName:@"Root"];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
// Memory management.
[aFetchedResultsController release];
[fetchRequest release];
[dateDescriptor release];
[nameDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
- (NSString *)transactionDay{
[self willAccessValueForKey:@"transactionDay"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM dd,yyyy"];
NSString*someString=[dateFormatter stringFromDate:[self valueForKey:@"myDate"]];
[self didAccessValueForKey:@"transactionDay"];
return someString;
}
The current error I am getting is "the entity Patient is not key value coding-compliant for the key "transactionDay""
Thanks, again.
When specifying the sectionNameKeyPath
, you have to include the entity attribute that you want to apply the transient attribute to ( ie, entityAttribute.transientAttribute
). So if you have an entity Patient
with an attribute myDate
of type NSDate
:
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"myDate.transactionDay"
cacheName:@"Root"];
The transient attribute can be defined in your Patient
implementation file by adding the following to the top:
@implementation NSDate (TransactionDayFormat)
- (NSString *)transactionDay{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM dd,yyyy"];
NSString*someString=[dateFormatter stringFromDate:self];
return someString;
}
@end
@implementation Patient
...
transactionDay
will process your myDate
attribute further, allowing you to specify sections to stricter formats. Note that NSDateFormatter
is quite a bulky object to initialise, so it may be worthwhile to declare it earlier and reference it later for efficiency.
-transactionDay
方法应该是您在Patient
类上实现的属性,然后可以根据此类(我猜测,该视图控制器)可以选择排序或分区。
Sounds like your are trying to initialise your fetchedResultsController with a sectionNameKeyPath that hasn't been declared as an attribute in your object model for Patient.
Can you confirm that transactionDay is defined as a NSString attribute in your Patient object model?
Also this sounds like a bit of a round about way to go about what you are trying to achieve. Perhaps you should try to remove the timestamp from your NSDate attribute instead? I did a quick search on SO can found this possible solution to removing NSDate's timestamp
-(NSDate *)dateWithOutTime:(NSDate *)datDate
if( datDate == nil ) {
datDate = [NSDate date];
}
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:datDate];
return [[NSCalendar currentCalendar] dateFromComponents:comps];
}
The link to the question is Removing time components from an NSDate object using Objective C/Cocoa
链接地址: http://www.djcxy.com/p/36120.html