I'm currently trying to sort my array of objects into day order so they can be grouped in the correct order i.e. Monday, Tuesday, Wednesday then by start time.
Only problem is I can't figure out how to do this, my code currently looks like this: Which sorts alphabetically then by time:
NSString *sectionKey = nil;
switch (tab) {
case kByWeekA: {
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"day" ascending:NO];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"starttime" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptor1 release];
[sortDescriptor2 release];
[sortDescriptors release];
sectionKey = @"da开发者_StackOverflow社区y";
break;
}
case kByWeekB:{
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"day" ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"starttime" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptor1 release];
[sortDescriptor2 release];
[sortDescriptors release];
sectionKey = @"day";
break;
}
default:
break;
}
Please help!
I see two solutions:
- Create a custom comparison for your sort descriptor that looks at the "day" key and orders them as desired. See Specifying Custom Comparisons here.
- Make the "day" key into an integer and use an enumeration for the day values in the desired order.
UPDATE 2 Example code for option 2:
-Change the "day" attribute to a number (Int16) and add a transient (non-persistant) "dayName" string attribute.
-Add this enumeration of the week days:
typdef enum {
kMonday,
kTuesday,
kWednesday,
kThursday,
kFriday,
kSaturday,
kSunday
} WeekDay;
-Set the "day" property of your managed objects to be NSNumber objects. For example:
object.day = [NSNumber numberWithInteger:kMonday];
-Implement the getter function for the transient "dayName" property:
- (NSString*)dayName {
switch ((WeekDay)self.day.integerValue) {
case kMonday:
return @"Monday";
break;
case kTuesday:
return @"Tuesday";
break;
case kWednesday:
return @"Wednesday";
break;
case kMonday:
return @"Monday";
break;
case kThursday:
return @"Thursday";
break;
case kFriday:
return @"Friday";
break;
case kSaturday:
return @"Saturday";
break;
case kSunday:
return @"Sunday";
break;
}
}
-In the fetch request, sort by "day" and use "dayName" as the section name key path.
UPDATE
Note: Option 1 works fine for sorting an array, but Core Data is throwing an 'NSInvalidArgumentException' exception for 'unsupported NSSortDescriptor selector: weekdayCompare:'
Example code for option 1:
// category on NSString for custom comparison
@interface NSString (WeekdayComparison)
- (NSComparisonResult)weekdayCompare:(NSString*)otherDay;
@end
@implementation NSString (WeekdayComparison)
- (NSComparisonResult)weekdayCompare:(NSString*)otherDay {
NSArray *weekDays = [NSArray arrayWithObjects:@"Sunday", @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", nil];
NSUInteger selfIndex = [weekDays indexOfObject:self];
NSUInteger otherDayIndex = [weekDays indexOfObject:otherDay];
if (selfIndex < otherDayIndex) {
return NSOrderedAscending;
}
else if (selfIndex > otherDayIndex) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
@end
To use the new comparison method:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"day" ascending:YES selector:@selector(weekdayCompare:)];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[sortDescriptor release];
I was working with the same requirements for custom sorting of sections and Solution #1 worked for me very well, thanks!
One thing I'd like to add is that after adding the transient property if your app crashes mysteriously a couple of seconds after loading, you need to reset your database.
NSError *error;
NSURL *applicationDocumentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *databaseURL = [applicationDocumentsDirectory URLByAppendingPathComponent:@"My Database Name"];
[[NSFileManager defaultManager] removeItemAtPath:databaseURL.path error:&error];
Hope this helps!
精彩评论