2012-05-12 46 views
1

我在一个NSDictionary下的一个NSDate密钥下存储了一个对象。然后我得到另一个具有相同日期值的NSDate,并用它从NSDictionary中检索对象。令我惊讶的是,它返回nil。但我的调试会话期间所透露吹我的脑海里更:两个具有相同日期值和相同散列值的NSDates如何不相等?

(LLDB)PO时
(NSDate的*)$ 34 = 0x0f8be100 2012-05-11 21点08分37秒+0000
(LLDB )PO [newTaskDict objectForKey:当]
(ID)$ 36 = 00000000
(LLDB)PO [newTaskDict allKeys]
(ID)$ 37 = 0x0f8c1650 < __NSArrayI 0xf8c1650>(
2012-05-11 21:08: 37 +0000

(lldb)po [[newTaskDict allKeys] lastObject]
(id)$ 38 = 0x0f8b5ff0 2012-05-11 21:08:37 +0000
(lldb)p(int)[[[newTaskDict allKeys] lastObject] isEqual:当]
(int)的$ 39 = 0
(LLDB)PO [[[newTaskDict allKeys] lastObject]类]
(ID)$ 40 = 0x3f4496b0 __NSDate
(LLDB)PO [当类]
(ID) $ 41 = 0x3f4496b0 __NSDate
(LLDB)p(INT)[[[newTaskDict allKeys] lastObject] isEqualToDate:当]
(int)的$ 42 = 0
(LLDB)P(INT)[[[newTaskDict allKeys] lastObject]散列]
(int)的$ 43 = 358463317
(LLDB)P(INT)[当散列]
(INT)$ 4×4 = 358463317

正如你所看到的,newTaskDict具有由原始NSDate其值是($ 38)键只有一个条目:
0x0f8b5ff0 2012-05-11 21:08:37 +0000
,其哈希($ 43):
35846331

我用来检索条目($ 34)其他NSDate
0x0f8be100 2012-05-11 21:08:37 +0000
其哈希($ 44):
358463317

是不是这两个NSDate正是除了自己的内存地址一样吗? isEqual:($ 39)和isEqualToDate:($ 42)怎么能为他们返回NO?

已解决:
这个奇怪的不平衡原来是由sub-second differences造成的。你必须在接受的答案下阅读我的第二条评论,因为它非常有趣,如果你不知道,它可能会在某一天引起你的反感。

回答

6

isEqualToDate:也将查看毫秒,通过记录对象无法看到该毫秒,因为NSDate的描述方法仅对人类友好的字符串进行格式化,但日期对象后面有更多信息。

看起来你的两个日期稍有不同,即使它们是在同一个运行循环中创建的,尝试创建一个并在2个引用中只使用一个对象,然后再执行第二个测试来检查两个日期,也可能会发生两个NSDate分开创建的对象 - 即使是一个接一个地创建,它们也不应该是平等的。

引述苹果文档:

这种方法检测的日期之间的子第二差异。如果您想比较不太精细的日期,请使用timeIntervalSinceDate:比较两个日期。

https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/nsdate_Class/Reference/Reference.html

+0

1)它是一个特定的时间值,而不是一个 “现在时刻” 从'[NSDate的日期]'得到。 2)正如你所看到的,我使用'NSDate'作为字典键,所以只有'isEqual:'对我来说是有意义的。我不能“使用timeIntervalSinceDate:比较两个日期”。 3)可悲的是,我已经失去了特定的'NSDate',现在我不能重复奇怪的不平等。 – an0

+0

正如文件所述,它也考虑到“日期之间的亚秒差异”,这将包括但不限于毫秒。 – Daniel

+0

经过一次实验后,我可以说它必定是导致这种奇怪不平等的“亚秒差异”。即使两个'NSDate'预计具有相同的特定时间值,后面的一个将从服务器返回。我猜在服务器存储'NSDate'时,会出现'sub-second'的精度损失。整件事似乎很奇怪,因为即使它们携带不同的秒秒值,两个'NSDate's也会返回相同的散列值。 – an0

1

isEqual to date compare to the microseconds。如果您需要更少的精度,请使用timeIntervalSinceDate:测试日期在彼此的微秒,秒,小时,天等范围内。

isEqual经常使用内存地址本身来决定它是否是同一个对象,因为如果它们具有不同的地址,它们是单独的对象。

相关问题