Cocoa基本原理指南之四 - Cocoa对象的生命周期

摘选自:http://www.apple.com.cn/developer/mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/Introduction/chapter_1_section_1.html

 

 

    CocoaObjective-C选择一种主动的、策略驱动的例程来保持对象,并在不再需要的时候进行清理。这种例程和策略建立在引用计数的基础上。每个Cocoa对象都带有一个整数,用于指示对其持久性感兴趣的其它对象的数目。这个整数被称为对象的保持数保持是为了避免和引用重复)。

    当通过alloc或者allocWithZone:类方法创建对象的时候,Cocoa做了一些非常重要的工作:

§  它将对象的isa指针NSObject类中唯一的公共实例变量指向对象的类,因此将对象集成到类层次的运行时视图中。

§  它将对象的保持数一个隐藏的实例变量,所有对象都有设置为1

    为对象分配内存之后,通常需要将其实例变量设置为合理的初始值,以便进行初始化(NSObject声明了init方法作为这个目的的原型)。

当释放一个对象也就是向对象发送一个release消息时—NSObject会减少它的保持数。如果保持数从1下降到0,对象就会被解除分配。对象的解除分配有两个步骤:首先是对象的dealloc方法被调用,以释放实例变量和动态分配的内存;然后是操作系统将对象的本身销毁,并回收对象占用的内存。如果不希望对象很快消失,在创建对象之后向它发送一个retain消息,对象的保持数就会增加到2。这样,就需要两个release消息才能导致对象的释放。

    重要提示:永远不应该直接调用对象的dealloc方法。

    如果客户对象在程序的作用域之外希望保持接收到的对象,则可以保持该对象也就是向它发送一个retain消息。保持一个对象会增加该对象的保持数,从而表示希望拥有该对象。客户对象有责任在一段时间后释放该对象。如果对象的创建者将该对象释放,但同时有一个客户对象已经保持了该对象,则该对象会一直持续到客户对象将它释放为止。可以不保持对象,而是通过发送copycopyWithZone:消息来对其进行拷贝(很多子类如果不是大多数的话都封装了某种数据采纳方法,或遵循这种协议)。拷贝一个对象不仅仅是对其进行复制,而且几乎总是将它的保持数设置为1。根据对象的本质和可能的用法,拷贝可以是浅拷贝,也可以是深拷贝。深拷贝将对象复制为被拷贝对象的一个实例变量,而浅拷贝只是复制那些实例对象的引用。

    Cocoa引入了一种延迟对象释放的机制,称为自动释放(autoreleasing)机制。自动释放机制通过自动释放池(由NSAutoreleasePool类定义)来实现。自动释放池是位于显式定义的作用域内的一个对象集合,该作用域被标志为最后释放。自动释放池可以嵌套。当您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放

    到目前为止,对象生命周期的讨论主要关注整个周期中的对象管理机制。但是,指导如何使用这些机制的是对象的所有权策略。这个策略可以概括如下:

§  如果通过分配和初始化(比如[[MyClass alloc] init])的方式来创建对象,就拥有这个对象,需要负责该对象的释放。这个规则在使    用NSObject的便利方法new时也同样适用。

§  如果拷贝一个对象,也拥有拷贝得到的对象,需要负责该对象的释放。

§  如果保持一个对象,就部分拥有这个对象,需要在不再使用时释放该对象。

    反过来,

§  如果从其它对象那里接收到一个对象,则不拥有该对象,也不应该释放它(这个规则有少数的例外,在参考文档中有显式的说明)。

    和其它规则一样,这些策略也有一些例外和经常出错的地方:

§  如果您通过类工厂方法来创建对象(比如NSMutableArray arrayWithCapacity:方法),则可以假定您接收到的对象已经自动被放到自动释放池了。您不应该自行将它释放,如果您需要保持该对象,则应该保持(retain)它。

§  为了避免循环引用,子对象不能保持它的父对象(父对象是该子对象的创建者,或者将该子对象作为实例变量持有的对象)。

    对象的生命周期中可能发生的另一个基本事件是归档。归档是将组成一个面向对象程序中的相关对象形成的网状结构对象图转化为一种可持久的形式(通常是一个文件),该形式可以保存对象图中对象的标识和彼此之间的关系。在解档时,可以通过这个档案重新构造出程序的对象图。为了参与归档(和解档),对象必须支持通过NSCoder类定义的方法对实例变量进行编码(和解码)。为了这个目的,NSObject采纳了NSCoding协议。

 

你可能感兴趣的:(Cocoa基本原理指南之四 - Cocoa对象的生命周期)