这可能是一个简单的问题,但为什么在我的课堂上实现 NSCopying 协议,我得到zone == nil
- (id)copyWithZone:(NSZone *)zone
{
if (zone == nil)
NSLog(@"why this is allways nil");
(...)
}
使用此方法调用带有对象的复制数组。
[[NSArray alloc] initWithArray:myArray copyItems:YES]];
这可能是一个简单的问题,但为什么在我的课堂上实现 NSCopying 协议,我得到zone == nil
- (id)copyWithZone:(NSZone *)zone
{
if (zone == nil)
NSLog(@"why this is allways nil");
(...)
}
使用此方法调用带有对象的复制数组。
[[NSArray alloc] initWithArray:myArray copyItems:YES]];
凯文和罗宾的回答是最准确的。奥斯卡的答案非常接近正确。但无论是 Gnustep 文档还是 logancautrell 存在区域的原因都不是完全正确的。
最初创建区域(首先是 NXZone,然后是 NSZone)是为了确保从单个区域分配的对象在内存中相对连续,这是真的。事实证明,这不会减少应用程序使用的内存量;在大多数情况下,它最终会略微增加它。
更大的目的是能够大规模摧毁一组物体。
例如,如果您要将复杂的文档加载到基于文档的应用程序中,那么在关闭文档时拆除对象图实际上可能会非常昂贵。
因此,如果一个文档的所有对象都是从单个区域分配的,并且该区域的分配元数据也在该区域中,那么销毁与该文档相关的所有对象将与简单地销毁该区域一样便宜(这实际上是便宜——“这里,系统,把这些页面拿回来”——一个函数调用)。
这被证明是行不通的。如果对区域中对象的单个引用泄漏到区域外,那么您的应用程序将在文档关闭后立即进入BOOM状态,并且该对象无法告诉任何引用它的内容停止。其次,这个模型也成为 GC 系统中经常遇到的“资源稀缺”问题的牺牲品。也就是说,如果文档的对象图持有非内存资源,则无法在区域销毁之前有效地清理所述资源。
最后,没有足够的性能优势(您真正关闭复杂文档的频率)与所有额外的脆弱性相结合,使区域成为一个坏主意。但是,更改 API 为时已晚,我们只剩下痕迹了。
NULL 区域仅表示“使用默认区域”。现代 Objective C 运行时不再使用区域,并且根本不能与 ARC 一起使用。
查看文档
NSZone
很久以前就被弃用了。它仍在方法签名(例如+allocWithZone:
和-copyWithZone:
)中的事实是为了向后兼容。
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 日以来,它在某个时候发生了变化。
NSZone
现在是一个未记录的类,因为它已经很老了,它的目的是使用同一组虚拟内存页面在堆上分配对象。然而,它大多不再使用,但由于它之前使用过,该参数仍然存在以实现向后兼容性。