从格式数据中获取按格式化日期排序

时间:2010-11-16 12:11:59

标签: objective-c sorting core-data nsfetchedresultscontroller nsdateformatter

我无法从按日期排序的Core Data中获取结果。

我有一个包含足球比赛的数据库表。每场比赛都有一个主队,客队和开球时间。 kickoffTime是一个NSDate,用于存储匹配开始的日期和时间。

我想在TableView中显示查询结果,并按启动日期划分为多个部分。将日期作为部分标题。

这比它最初出现的要复杂得多。由于时区不同,从世界某一地区的一个日期开始的匹配实际上是在世界其他地方的不同日期开始。因此,我不能简单地忽略时间并将启动日期存储在另一列中。

我正在尝试创建一个自定义访问器,它返回一个格式化的日期,在用户所在的任何时区,然后使用它来对结果进行排序和分区。这是我在Match.h中的代码:

@dynamic kickoffTime;
@dynamic formattedKickoffTime;
@dynamic dateFormatter;

- (NSString *)formattedKickoffTime
{
    [self willAccessValueForKey:@"kickoffTime"];

    // Set the date formatter to the format we want to display the date
    [dateFormatter setDateFormat:@"ccc, d MMM"];

    // Format the date
    NSString *myFormattedKickoffTime = [dateFormatter stringFromDate:[self kickoffTime]];

    [self didAccessValueForKey:@"kickoffTime"];

    // return the formatted date
    return myFormattedKickoffTime;
}

- (NSDateFormatter *)dateFormatter 
{   
    if (dateFormatter == nil) 
    {
        dateFormatter = [[NSDateFormatter alloc] init];
    }
    return dateFormatter;
}

@end

然而,当我尝试像这样获取和排序数据时:

NSSortDescriptor *kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:@"formattedKickoffTime" ascending:YES];
...
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"formattedKickoffTime" cacheName:nil];

我收到以下错误消息:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath formattedKickoffTime not found in entity <NSSQLEntity Match id=1>'

有人会提供一些建议吗?

1 个答案:

答案 0 :(得分:0)

所以我找到了一种方法来做到这一点。首先,我将模型中的所有日期和计算保留在GMT中。我将一个自定义访问器(kickoffDate)添加到我的Match实体,它获取kickoffTime,将它的时间设置为00:00:00并返回此值。我不得不做的一件事,那就是设置自定义访问者返回GMT的日期的时区,否则将其设置为用户的系统timeZone。

由于模型返回的所有日期都在GMT中,因此无论我在iPhone的设置中设置了什么时间区域,一切似乎都能正常工作。我猜Core Data足够智能,可以在将匹配放入各个部分之前进行timeZone调整。

我确实有一个问题,[NSTimeZone timeZoneForSecondsFromGMT:0]是获得0时区的最佳方法,我的意思是一个不受夏令时影响的时区吗?

哦,我是否必须致电[self willAccessValueForKey:@"kickoffTime"];[self didAccessValueForKey:@"kickoffTime"];?我真的不明白这些是做什么的!

这是Match.h中的代码:

...
@dynamic homeTeam;
@dynamic awayTeam;
@dynamic kickoffTime;

- (NSDate *)kickoffDate
{
    [self willAccessValueForKey:@"kickoffTime"];
    NSCalendar *cal = [NSCalendar currentCalendar];
    NSDateComponents *components = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:[self primitiveValueForKey:@"kickoffTime"]];
    [components setHour:0];
    [components setMinute:0];
    [components setSecond:0];
    [components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

    [self didAccessValueForKey:@"kickoffTime"];
    return [cal dateFromComponents:components];
}

然后我的fetch代码包含以下对kickoffTime的排序,sectionNameKeyPath设置为kickoffDate:

NSSortDescriptor *kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:@"kickoffTime" ascending:YES];
...
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"kickoffDate" cacheName:nil];