UITableView 部分中的 NSDates 不反映来自 UIDatePicker 的日期
Posted
技术标签:
【中文标题】UITableView 部分中的 NSDates 不反映来自 UIDatePicker 的日期【英文标题】:NSDates in a UITableView Section are not reflecting dates from a UIDatePicker 【发布时间】:2014-09-17 12:28:18 【问题描述】:我有一个带有UITableViewController
的简单应用程序,它由用户填写a 并在不同的视图中从UIDatePicker
中选择一个日期。 UITableView
的 cells
填充有来自 UITextField
的词,而 UITableView
section
标题表示来自 UIDatePicker
的选定日期。
当用户保存在Add Entry View Controller,
中时,它会保存到Core Data
并且NSFetchedResultsController
负责更新UITableView
。
在我的应用程序的早期版本(2.0 版)中,我遇到了一个错误,即美国时区总是将部分标题显示为UIDatePicker
中所选日期的前一天。对其他国家来说很好。 NSDate 与 UTC 时区一起存储。
我通过将UIDatePicker
设置为不使用版本 2.1.1 的任何时区来实施修复。我认为已经修复了它,但进一步的测试使我发现了其他错误。
我现在正在尝试解决这个问题。
我有一个Transient
属性,用于部分标题如下:
-(NSString *)sectionDateFormatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"d MMMM yyyy"];
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSDate *thisDate = self.dates.dateOfEvent;
NSString *stringDate = [dateFormatter stringFromDate:self.dates.dateOfEvent];
NSLog(@"[Transaction] The NSDate of self.dates.dateOfEvent = %@", thisDate);
NSLog(@"[Transaction] The NSDate converted into a string = %@", stringDate);
return [dateFormatter stringFromDate:self.dates.dateOfEvent];
我的模型是:Transaction Entity
与 Dates Entity
有关系,datesOfEvent
是 NSDate
。我将其转换为字符串,以便以我想要的格式轻松显示为section
标题。
问题
如果我从新安装我的应用程序开始,这会非常有效,并且在 Add Entry View Controller
中,我已将 UIDatePicker
设置为也使用 GMT 时区。
但是,如果我从版本 2.1.1 更新,我的所有 EXISTING* 条目的日期都会在 UITableView
的 section
标题中后移一位。我的意思是:
如果我在 2.1.1 版中有 1 个 9 月 17 日的条目、15 日的一个条目和 10 日的一个条目(只是日期的一个例子),当我更新到我正在开发的这个新版本时,所有章节标题都可以追溯到 9 月 16 日、9 月 14 日和 9 月 9 日。如果我单击该条目,UIDatePicker
将显示它应该是的日期(而不是 section
标题中显示的日期)。因此,如果我单击第一个条目,UIDatePicker
会显示第 17 个,但 section
标题会显示第 16 个。
这与时区无关。
我不确定我需要做些什么来确保更新的用户有相同的日期,并且新用户也没有问题。为什么一切都往前追溯?
当我在更新后运行应用程序时,NSLogs 输出显示: [交易] self.dates.dateOfEvent 的 NSDate = 2014-09-16 23:00:00 +0000 [Transaction] NSDate 转成字符串 = 16 September 2014
我不明白为什么dateOfEvent
在 23:00 是第 16 位,而字符串显示的是第 16 位。我不明白为什么日期会向后移动。
*EXISTING:我已经清楚地标记了这一点,因为更新版本中的新条目可以正常工作,但现有条目是它们的日期在章节标题中移回的条目。
请记住,在 2.1.1 版中,我没有在 Transient
属性中为 section
标题使用 GMT 的代码。由于时区的一些奇怪行为,这只是我现在在开发过程中介绍的内容。
更新:显示日期的存储方式
在添加条目的保存方法中,在 2.1.1 版本中,我这样做:
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//cal.timeZone = [NSTimeZone localTimeZone];
NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:self.datePicker.date];
//[components setTimeZone:[NSTimeZone localTimeZone]];
NSDate *selectedDate = [cal dateFromComponents:components];
// Call the date category and check whether the value exists; if it does return, etc.
Date *date = (Date *)[Date occasionWithDate:selectedDate inManagedObjectContext:context];
所以,我已经为日历和 NSDateComponents 输入了 localTimeZone,但是我在发布的 2.1.1 版本中注释掉了代码。
在 2.0 版中,我有:
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:self.datePicker.date];
[components setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
NSDate *selectedDate = [cal dateFromComponents:components];
// Call the date category and check whether the value exists; if it does return, etc.
Date *date = (Date *)[Date occasionWithDate:selectedDate inManagedObjectContext:context];
我将 NSDateComponents 的时区设置为 UTC。
在 2.2 版(我正在开发的版本)中,我正在设置:
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:self.datePicker.date];
self.datePicker.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
components.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSDate *selectedDate = [cal dateFromComponents:components];
// Call the date category and check whether the value exists; if it does return, etc.
Date *date = (Date *)[Date occasionWithDate:selectedDate inManagedObjectContext:context];
我将其设置为 GMT 时区。
对此的任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:NSDate 包含一个 UTC 时间点(大致是格林威治标准时间,没有夏令时)。它没有时区信息。如果我们同时看手表,我们可能会看到不同的时间,因为我们在不同的位置。但是,如果我们的应用程序同时调用 [NSDate date],我们会看到相同的结果。
您应该始终未修改地存储 NSDate,并使用 NSTimeZone 和 NSDateFormatter 方法向用户显示时间。如果 NSLog (@"%@", [NSDate date])) 显示出你意想不到的东西,这是绝对正常的,因为它以 UTC 显示时间。通过 NSDateFormatter 向用户显示的文本应该不同。
我想说你需要从你正在做的事情中退后一步,找出你为现有日期存储的确切内容。您是否存储了正确的 NSDate 或者您是否以某种方式针对时区进行了调整?如果您的新代码同时存储不同的 NSDates,那么显然有些事情是行不通的。
【讨论】:
非常感谢@gnasher729 的回复,您的解释非常有道理。我更新了我的问题以反映存储日期的代码。在 2.0 版中,我将其存储为 UTC。在 2.1.1 中,我根本没有设置时区(我有一些奇怪的问题,我认为没有设置时区有效.. 但它在这个问题中引起了这个问题)和 2.2 版(我目前正在工作的版本on),我将其设置为 GMT。问题是从 2.1.1 到 2.2(2.0 到 2.1.1 很好).. 所以没有设置时区,我搞砸了.. 所以看起来向用户显示的日期是什么搞砸了..它作为一个时区设置,并且在升级时与 UIDatePicker 有所不同。此外,重要的是要提到版本 2.1.1(和 2.0)没有在 sectionDateFormatter 瞬态属性中设置任何时区;这是我现在在 2.2 版中添加的代码。 我有一个可行的解决方案,就是回到代码工作的地方,然后在下一个版本中更新 Transaction.m。这有点像黑客,但它可以满足我的要求。感谢您对此的回复,它确实帮助我指明了正确的方向,我非常感谢!以上是关于UITableView 部分中的 NSDates 不反映来自 UIDatePicker 的日期的主要内容,如果未能解决你的问题,请参考以下文章