首页 文章

UIDatePicker和美国/加拿大时区通过日期弄乱了NSFetchRequest过滤器

提问于
浏览
0

我有一个带有两个标签的 UITabBarController (时间轴和日期);两者都是 UITableViewControllers . 用户通过点击 UINavigationBar 按钮然后填写姓名,事件,金额和日期等信息,将信息添加到这些表视图中 . 前三个是 UITextFields ,日期是 UIDatePicker . 保存到 Core-Data 的信息后, UITableViewController 将使用 NSFetchedResultsControllers 进行更新 .

CoreData的模型是与年份实体有关系的交易实体 . 我还有一个年度实体来检查其他地方的日期(但不仅仅是几年) .

第二个标签是一个“日期”标签,仅根据日期中的年份进行过滤,因此,如果用户有2014年的5个条目,它将仅显示2014年一次,然后当用户点击2014年单元格时,它们'将查看年份= 2014年的所有条目 . 这同样适用于其他年份 .

Problem

我在英国的区域设置,但我编写应用程序的Mac是在美国本地,我刚刚注意到一个大问题 .

如果您在devie上将时区更改为新加坡或亚洲(及时在英国前面的某个地方),则日期选项卡将与您保留的时区保持一致 . 但是,如果您通过电话,墨西哥或加拿大(通常在英国之后的任何时间)将其更改为纽约,那么“日期”选项卡会每年减少一次 .

我的意思是,如果你有2014年,2013年,2012年的日期标签,而你在英国地区,如果你去纽约时区进入应用程序,它现在显示2013年,2012年和2011年 .

到底是怎么回事?

这是添加条目的“保存”方法中的一些代码:

NSCalendar *yearCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *yearComponent = [yearCal components:NSYearCalendarUnit fromDate:self.datePicker.date];
[yearComponent setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
NSDate *selectedYear = [yearCal dateFromComponents:yearComponent];

// Calling the year category to check whether it exists.
Years *years = (Years *)[Years matchingYear:selectedYear inManagedObjectContext:context];
transaction.years = years;

这会调用年份 Entity 上的类别:

+ (Years *)matchingYear:(NSDate *)enteredYear inManagedObjectContext:(NSManagedObjectContext *)context
{
    Years *years = nil;

    // Creating a fetch request to check whether the year already exists, calling from the Add/DetailViewController.
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Years"];
    request.predicate = [NSPredicate predicateWithFormat:@"yearOfEvent = %@", enteredYear];
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"yearOfEvent" ascending:YES];
    request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    NSError *error = nil;
    NSArray *matchedYears = [context executeFetchRequest:request error:&error];
    if (!matchedYears)
    {
        // No errors to handle
    }
    else if (![matchedYears count])
    {
        // If the year count is 0 then create it
        years = [NSEntityDescription insertNewObjectForEntityForName:@"Years" inManagedObjectContext:context];
        years.yearOfEvent = enteredYear;
    }
    else
    {
        // If the year exists, return it.  
        years = [matchedYears lastObject];
    }
    return years;

}

我的UIDatePicker设置为当前日期,因此用户将来无法选择日期 .

这是日期选项卡的fetchResultsController代码:

- (NSFetchedResultsController *)fetchedResultsController
{
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    if (_fetchedResultsController != nil)
    {
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Years" inManagedObjectContext:managedObjectContext];
    fetchRequest.entity = entity;
    NSPredicate *d = [NSPredicate predicateWithFormat:@"transactions.years.@count !=0"];
    [fetchRequest setPredicate:d];
    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"yearOfEvent" ascending:NO];
    fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
    fetchRequest.fetchBatchSize = 20;
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

在我的保存方法中,我注意到我将时区设置为UTC,我之所以这样做是因为如果我没有,当我去另一个国家并更改我的时区时,它会为每个条目添加“2014” 2014年在日期标签中显然是错误的 . 但这当然会导致一些问题 .

Requirement

我只需要能够保持日期选项卡相同,无论我在哪个时区 .

Key Points

格式保存的原因有几个原因,因为它会影响整个应用程序,因此无法更改 . UIDatePicker在Storyboard中设置为UK Locale,原因如下 . 但是,即使将语言环境设置为“默认”,也会出现同样的问题 . 美国和加拿大的时区消除了一年,因此2014年成为2013年,2013年成为2012年,2012年成为2011年的日期标签 . 这对我来说没有意义 .

任何有关这方面的指导都将非常感谢!

1 回答

  • 2

    发生了什么事?

    发生的事情是,无论时区如何,保持日期一致的要求并不像你想的那么容易 . 就像这样:

    • NSDate 没有时区概念 . 它基本上是 NSTimeInterval 的对象包装器,用于测量自UTC参考日期以来的时间 .

    • NSDate 转换为人类可读的内容时,时区适用于转换 . 它必须申请,因为当你要求对应于 NSDate 的日期时,你必须回答问题,日期,地点,确切地说?

    您的初始保存代码可以解决此问题:

    NSCalendar *yearCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *yearComponent = [yearCal components:NSYearCalendarUnit fromDate:self.datePicker.date];
    [yearComponent setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    NSDate *selectedYear = [yearCal dateFromComponents:yearComponent];
    

    如果所选日期为今天,则最终NSDate自参考日期起为410227200秒,其中UTC对应于2014年1月1日00:00:00 . 在UTC以东的时区中,它是一个或多个小时后,即2014年在UTC以西的时区,它早一个或多个小时,现在仍然是2013年 . 问题的每一个细节都源于这个事实 .

    如果你关心这一年,最好的解决方案是 store the year ,而不是 NSDate . 将2014,2013,2012等存储为整数而不是 NSDate 所暗示的值 .

    顺便提一下,这部分问题完全无关紧要:

    我在英国的语言环境,但我编写应用程序的Mac是在美国本地,我刚刚发现了一个大问题 .

    重要的是运行代码的设备上的时区,而不是用于编译和链接该代码的设备上的区域 .

相关问题