15

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

- (id)copyWithZone:(NSZone *)zone
{
    if (zone == nil)
        NSLog(@"why this is allways nil");

    (...)
}

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

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

5 回答 5

25

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

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

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

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

因此,如果一个文档的所有对象都是从单个区域分配的,并且该区域的分配元数据也在该区域中,那么销毁与该文档相关的所有对象将与简单地销毁该区域一样便宜(这实际上是便宜——“这里,系统,把这些页面拿回来”——一个函数调用)。

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

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

于 2011-10-28T22:05:43.533 回答
4

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

查看文档

于 2011-10-28T19:57:50.940 回答
3

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

于 2011-10-28T19:56:47.027 回答
1

Zone 是旧时代的遗留物,当时计算机的 RAM 为 8 兆或更少。

看看这个(3.1.2 内存分配和区域):

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

大约 10 年前,在 cocoa builder 上也有一个很好的讨论(好吧,它在可可开发邮件列表上)。这正是@bbum 所说的。

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

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

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

于 2011-10-28T19:56:18.943 回答
1

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

于 2011-10-28T19:56:26.680 回答