I hope someone can give me some helpful suggestions on what to do about this.
I have been trying several ways to sort a set of entities that have the relationship client<-->>job based on a custom accessor for a property of client as the first sort descriptor, and then the job description property as the second sort descriptor.
I first tried to use a transient property, called Client.sortValue, and discovered that transient properties can't be used as sort descriptors with the NSFetchedResultsController. So I changed the property Client.sortValue to be non-transient.
I never save a value for sortValue to the persistent store. Instead, I use a custom accessor. Apparently, the custom accessor method is not being used when the fetechedResultsController performFetch: method is run. It is called when I do logging, as shown in the code below. I can see that this is the case using a break point in the custom accessor and viewing the stack trace. I don't see it break on the accessor method when the performFetch is run, but it does break on the accessor method when the logging is done.
(Strangely, I had it working earlier today under some circumstances, but not others. It was obviously being sorted the way I wanted it to be, but after I refactored my code to track down the conditions where it worked, I have not seen it work again.)
I have tried various custom accessor methods, including the following:
- (NSString *) primitiveSortValue {
NSString *retVal = nil;
[self willAccessValueForKey:@"lastName"];
[self willAccessValueForKey:@"firstName"];
[self willAccessValueForKey:@"company"];
if (![self.lastName isNullString] ) retVal = [self primitiveValueForKey:@"lastName"];
else if (![self.firstName isNullString] ) retVal = [self primitiveValueForKey:@"firstName"];
else if (![self.company isNullString] ) retVal = [self primitiveValueForKey:@"company"];
else retVal = @"";
[self didAccessValueForKey:@"lastName"];
[self didAccessValueForKey:@"firstName"];
[self didAccessValueForKey:@"company"];
NSLog(@"Sort Value: %@", retVal);
return retVal;
}
I also tried this one before deciding to override the primitive accessor method:
- (NSString *) sortValue {
NSString *retVal = nil;
if (![self.lastName isNullString] ) retVal = self.lastName;
else if (![self.firstName isNullString] ) retVal = self.firstName;
else if (![self.company isNullString] ) retVal = self.company;
else retVal = @"";
NSLog(@"Sort Value: %@", retVal);
return retVal;
}
Here is my fetchedResultsController method:
#define CLIENT_SORT_KEY @"clientOfJob.sortValue"
- (NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:@"Job" inManagedObjectContext:dataInterface.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:10];
if (segmentedControl.selectedSegmentIndex == 0) { // sort by client, then job dscription
NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:CLIENT_SORT_KEY ascending:YES];
NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"jobDescription" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:dataInterface.managedObjectContext
sectionNameKeyPath:CLIENT_SORT_KEY
cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[jobSortDescriptor release];
[clientSortDescriptor release];
[sortDescriptors release];
}
else { // sort by job description
... }
NSError *error = nil;
if (![fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved Error %@, %@", error, [error userInfo]);
abort();
}
int i = 0;
for (id<NSFetchedResultsSectionInfo> sectionItem in [fetchedResultsController sections]){
NSLog(@"\n***********\nsection %d name %@\n-----------\n",i++, [sectionItem name]);
int j = 0;
for (Job *jobItem in [sectionItem objects]) {
NSLog(@"%d job: %@, client: %@\n",j, jobItem.jobDes开发者_JS百科cription, jobItem.clientOfJob.sortValue);
}
}
return fetchedResultsController;
}
精彩评论