为啥在实施 NSCopying 时 zone 总是为零?

Posted

技术标签:

【中文标题】为啥在实施 NSCopying 时 zone 总是为零?【英文标题】:Why zone is always nil while implementing NSCopying?为什么在实施 NSCopying 时 zone 总是为零? 【发布时间】:2011-12-17 13:28:52 【问题描述】:

这可能是一个简单的问题,但是为什么在我的课堂上实现 NSCopying 协议,我得到 zone == nil

- (id)copyWithZone:(NSZone *)zone

    if (zone == nil)
        NSLog(@"why this is allways nil");

    (...)

使用此方法调用带有对象的复制数组。

[[NSArray alloc] initWithArray:myArray copyItems:YES]];

【问题讨论】:

【参考方案1】:

凯文和罗宾的回答是最准确的。奥斯卡的答案非常接近正确。但无论是 Gnustep 文档还是 logancautrell 对区域存在的理由都不完全正确。

最初创建区域 - 首先是 NXZone,然后是 NSZone - 以确保从单个区域分配的对象在内存中相对连续,这是真的。事实证明,这不会减少应用程序使用的内存量;在大多数情况下,它最终会略微增加。

更大的目的是能够大规模摧毁一组物体。

例如,如果您要将复杂的文档加载到基于文档的应用程序中,则在关闭文档时拆除对象图实际上可能会非常昂贵。

因此,如果文档的所有对象都是从单个区域分配的并且该区域的分配元数据在该区域中,则销毁所有对象与文档相关的成本就像简单地破坏区域一样便宜(这真的很便宜——“这里,系统,把这些页面拿回来”——一个函数调用)。

这被证明是行不通的。如果对区域中对象的单个引用泄漏到区域之外,那么一旦文档关闭,您的应用程序就会BOOM,并且对象无法告知所指的内容它停止。其次,这个模型也成为了 GC 系统中经常遇到的“稀缺资源”问题的牺牲品。也就是说,如果文档的对象图持有非内存资源,则无法在区域销毁之前有效地清理这些资源。

最后,没有足够的性能优势(您真正关闭复杂文档的频率)加上所有额外的脆弱性使得区域成为一个坏主意。但是,更改 API 为时已晚,我们只剩下痕迹。

【讨论】:

太棒了,我希望你能回答这个问题。旁注,这是否在任何时候都记录在 Apple 文档中?我今天能找到的只有 NSZone* 基础方法。 如果您有类似的问题想引起我的注意,请随时在 Twitter 上 @bbum me。语言(和操作系统)的演变真的很吸引人。如果它被记录在案,它很可能是狂想曲时代的遗留物。我认为在适当的 Mac OS X 版本中从未推荐过区域。 我很感激,由于您独特的职位和历史,您的帖子受到高度重视。我希望有更多的 Apple 工程师在这里度过!【参考方案2】:

NULL 区域仅表示“使用默认区域”。现代的 Objective C 运行时不再使用区域,并且根本不能与 ARC 一起使用。

见documentation

【讨论】:

【参考方案3】:

NSZone 很久以前就被弃用了。事实上它仍在方法签名中(例如+allocWithZone:-copyWithZone:)是为了向后兼容。

【讨论】:

如果不推荐使用copyWithZone(NSCopying协议定义中没有提到),这些天如何使用所需的copyWithZone实现NSCopying? -copyWithZone: 未被弃用。 NSZone 是。只需忽略 zone 参数。【参考方案4】:

NSZone 现在是一个未记录的类,因为它已经很老了,它的目的是使用相同的虚拟内存页集在堆上分配对象。但是它大多不再使用,但由于它以前使用过,该参数仍然存在以实现向后兼容性。

【讨论】:

【参考方案5】:

Zone 是过去计算机内存只有 8 兆或更少的遗留物。

检查一下(3.1.2 内存分配和区域):

http://www.gnustep.org/resources/documentation/Developer/Base/ProgrammingManual/manual_3.html

大约 10 年前,在 cocoa builder 上也对此进行了很好的讨论(好吧,它在 cocoa dev 邮件列表上)。这正是@bbum 所说的。

http://www.cocoabuilder.com/archive/cocoa/65056-what-an-nszone.html

显然,这曾经记录在 Apple 文档中,但自 2007 年 6 月 6 日以来,它在某个时候发生了更改。

http://www.cocoadev.com/index.pl?NSZone

【讨论】:

以上是关于为啥在实施 NSCopying 时 zone 总是为零?的主要内容,如果未能解决你的问题,请参考以下文章

实施 NSCopying

iOS-NSCopying 和 NSMutableCopying协议

自定义的类实现copy操作

为啥我在图中的 DFS 循环检测总是返回 true?

在子类的子类中实现 NSCopying

Cocoa 的 NSDictionary:为啥要复制密钥?