这可能是一个简单的问题,但为什么在我的类中实现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]];
Kevin和Robin的回答是最准确的。Oscar的回答也非常接近正确。但是,Gnustep文档和logancautrell关于zones存在的原因并不完全正确。
创建zone最初是为了确保从单个zone分配的对象在内存中相对连续,这是真实的。事实证明,这并没有减少应用程序使用的内存量;在大多数情况下,它会稍微增加。
更大的目的是能够批量销毁一组对象。
例如,如果您将一个复杂的文档加载到基于文档的应用程序中,在关闭文档时撤销对象图可能会非常昂贵。
因此,如果文档的所有对象都从一个单独的zone分配,而该zone的分配元数据也在该zone中,则与文档相关的所有对象的销毁成本将与仅销毁zone一样便宜(这真的很便宜--“系统,有这些页面” - 一个函数调用)。
这被证明是行不通的。如果指向区域之外的对象的单个引用泄漏出区域,则在关闭文档并且对象无法告诉任何引用它的东西停止时,应用程序将立即崩溃。其次,该模型还遭受了在GC系统中经常遇到的“稀缺资源”问题。也就是说,如果文档的对象图保存了非内存资源,则在销毁zone之前没有有效清理这些资源的方法。
最后,由于所有增加的脆弱性并没有带来足够的性能提升(您有多少次会关闭复杂的文档),因此zones是一个糟糕的想法。尽管如此,API已无法更改,我们只能留下残余物。
NSZone
已经被废弃很久了。它仍然存在于方法签名中(例如 +allocWithZone:
和 -copyWithZone:
),是为了保持向后兼容。
-copyWithZone:
没有被弃用,只有 NSZone
被弃用了。忽略掉 zone
参数即可。 - Lily BallardZone是一个遗留问题,它来自于计算机只有8兆字节或更少的RAM的旧时代。
请查看(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
显然,这曾经在苹果文档中有记录,但自2007-06-06以来已经发生了变化。
NSZone
现在是一个未记录的类,因为它相当古老,其目的是使用相同的虚拟内存页面在堆上分配对象。然而,它现在大多数情况下不再使用,但由于它以前被使用过,该参数仍然存在以保持向后兼容性。