从核心提取按格式化日期排序的数据 [英] Fetch from Core Data sorted by formatted date

查看:256
本文介绍了从核心提取按格式化日期排序的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



我想在一个TableView中显示一个查询的结果, 。将日期作为节标题。



这比它首次出现的复杂一点。由于不同的时区,在世界的一部分中的一个日期开始的匹配实际上开始于世界的另一部分中的不同日期。所以我不能简单地忽略时间,并将开始日期存储在另一列中。



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

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

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

//将日期格式化设置为我们要显示日期的格式
[dateFormatter setDateFormat:@ccc,d MMM];

//格式化日期
NSString * myFormattedKickoffTime = [dateFormatter stringFromDate:[self kickoffTime]];

[self didAccessValueForKey:@kickoffTime];

//返回格式化的日期
return myFormattedKickoffTime;
}

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

@end

并对数据进行排序:

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

我收到以下错误讯息:

  ***由于未捕获异常NSInvalidArgumentException而终止应用程序,原因:'keypath formattedKickoffTime在实体中找不到< NSSQLEntity Match id = 1>'
解决方案

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



由于模型返回的所有日期都在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];
}

然后我的获取代码包括以下在kickoffTime上的排序,sectionNameKeyPath设置为kickoffDate:

  NSSortDescriptor * kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:@kickoffTimeascending:YES]; 
...
NSFetchedResultsController * aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@kickoffDatecacheName:nil];


I am having trouble fetching results from Core Data that are sorted by date.

I have a DB table that contains football matches. Each match has a homeTeam, awayTeam and kickoffTime. The kickoffTime is an NSDate that stores the date and time the match will start.

I want to display the results of a query in a TableView divided into sections by the kickoff date. With the date as the section heading.

This is a little more complex than it might first appear. Due to differing time zones a match starting on one date in one part of the world is actually starting on a different date in another part of the world. So I can't simply ignore the times and store the kickoff dates in another column.

What I'm trying to do create a custom accessor that returns a formatted date, in whatever time zone the user is in, and then use this to sort and section the results. Here's my code in 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

However when I try to fetch and sort the data like so:

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

I get the following error message:

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

Would someone offer some advice please?

解决方案

So I've found a way to do this. First of all I keep all the dates and calculations in the model in GMT. I add a custom accessor (kickoffDate) to my Match entity that gets the kickoffTime, sets it's time to 00:00:00 and returns this. One thing I had to do, that wasn't obvious, was set the timeZone of the date returned by the custom accessor to GMT as otherwise this was being set to the user's system timeZone.

As all the dates returned by the model are in GMT everything just seems to work as it should no matter what timeZone I set in the iPhone's Settings. I guess Core Data is smart enough to do the timeZone adjustments before it puts the matches in the sections.

I do have one question though, is [NSTimeZone timeZoneForSecondsFromGMT:0] the best way to get a 0 timeZone, by this I mean a timeZone that isn't affected by daylight saving time?

Oh and do I have to call [self willAccessValueForKey:@"kickoffTime"]; and [self didAccessValueForKey:@"kickoffTime"];? I don't really understand what these are doing!

Here's the code in 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];
}

And then my fetch code includes the following a sort on kickoffTime and the sectionNameKeyPath is set to kickoffDate:

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

这篇关于从核心提取按格式化日期排序的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆