【问题标题】:Fetch from Core Data sorted by formatted date从按格式化日期排序的核心数据中获取
【发布时间】:2010-11-16 12:11:58
【问题描述】:

我无法从 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>'

有人能给点建议吗?

【问题讨论】:

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


    【解决方案1】:

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

    由于模型返回的所有日期都是格林威治标准时间,所以无论我在 iPhone 的设置中设置什么时区,一切似乎都可以正常工作。我猜 Core Data 足够聪明,可以在将匹配项放入部分之前进行时区调整。

    不过,我确实有一个问题,[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];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多