【问题标题】:Copying an NSDate (wanting independent objects)复制 NSDate(想要独立对象)
【发布时间】:2011-12-14 16:48:40
【问题描述】:

NSDate 符合 NSCopying 协议。根据 NSCopying 协议的文档:

a copy must be a functionally independent object with values identical
to the original at the time the copy was made.

但是,当我这样做时:

NSDate *date1 = [NSDate date];
NSDate *date2 = [date1 copy];
NSLog(@"result: date1 0x%x  date2 0x%x", (int)date1, (int)date2);
// "result: date1 0x2facb0  date2 0x2facb0"

这两个对象是相同的(相同的对象 id)。我错过了什么?如何获取独立对象作为副本?

【问题讨论】:

  • 你不需要一个独立的对象。 NSDates 是不可变的。您无法更改它们,因此 -copy 返回相同的对象无关紧要。
  • 应该注意的是,Objective-C 架构允许将某些不可变的“对象”实现为指针中的自包含值。即,使用指针中的几个保留位来标识类型,指针值的其余部分实际上可以是“对象”。我不知道 Apple 是否承认对任何对象执行此操作,但对于 NSDate 对象和几种 NSNumber 风格显然是可行的。

标签: objective-c nsdate


【解决方案1】:

copy 不保证不同的对象指针。 “功能独立”意味着对原始对象的更改不会反映在副本中,因此对于不可变对象copy 可能会像retain 一样工作(我不知道这是否可以保证,可能不是)。

试试date2 = [[NSDate alloc] initWithTimeInterval:0 sinceDate:date1]

【讨论】:

  • 甚至:date2 = [date1 dateByAddingTimeInterval:0];
  • 我认为这不再有效(请参阅下面的答案)。
【解决方案2】:

小心!

我最近发现,在 iOS 8.1(.0) 上 [NSDate dateWithTimeInterval:0 sinceDate:date1] 返回 date1!甚至 alloc/init 返回相同的对象。

深拷贝对我来说很重要,因为我创建了对象的副本。稍后我将时间戳与[date1 laterDate:date2] == date2 进行比较,如果深拷贝不起作用,这将始终为真。

[date1 dateByAddingTimeInterval:0] 也一样

我还没有适用于 iOS 8.1 的好的解决方案,但请继续搜索并在此处更新。紧急解决方法可能是使用格式化程序创建日期字符串,然后使用相同的格式化程序从字符串创建日期。

编辑:情况更糟:

NSString *date1String = [iso8601DateFormatter stringFromDate:date1];
date2 = [iso8601DateFormatter dateFromString:date1String];

(lldb) p date1
(NSDate *) $0 = 0xe41ba06fd0000000 2014-11-03 01:00:00 CET
(lldb) p date2
(NSDate *) $1 = 0xe41ba06fd0000000 2014-11-03 01:00:00 CET

【讨论】:

  • 呃,先生,你读了吗?这都是关于深度复制 NSDate 的。我的回答通过警告扩展了解决方案,它在 iOS 8.1 下不起作用。
  • 复制NSDate会解决什么问题? (将日期与== 进行比较的目的是什么?)
  • 呃,先生,你又读了吗?我引用我的回答:...我将时间戳与 [date1 laterDate:date2] == date2 进行比较,如果深拷贝不起作用,这将始终为真。 简单示例:您创建一些具有时间戳属性的对象。在某些时候,您出于任何原因想要创建对象的深层副本,例如移动到另一个上下文,它需要是一个不同的对象。在某些时候,您比较两个上下文的对象以找到较新的对象,并且 [date1 laterdate:date2] == date2 将始终为真。
  • 这实际上并不重要,因为我的回答仍然是一个扩展,以警告读者所选择的解决方案,这种深度复制在 iOS 8.1 下不起作用。深度复制的目的是完全无关的。
  • 由于不需要复制 NSDate 对象,因此您的“警告”是无关紧要的。
【解决方案3】:

NSDate 是抽象类。它经常使用'tagged pointer' trick,因此在大多数情况下,不可能在同一日期获取不同的对象。在这种情况下,真实的类名NSTaggedDate。 某些日期可能是真实对象(如果标记指针中没有空格)。例如:

    [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:1234567890123456]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2021-09-12
    • 2012-08-26
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    相关资源
    最近更新 更多