对一个程序来说,最好是尽可能少地使用内存。因此,Objective-C环境中定义了一些机制和策略,允许您对程序的内存进行管理。虽然您可以从底层实现的角度去考虑Objective-C程序的内存管理(详见“幕后:保留计数”),但是通常从对象所有权的角度来考虑这个问题会更容易。
在 Objective-C 程序中,对象会被创建和销毁。为了确保您的应用程序不会使用不必要的内存,对象应该在不需要它们的时候被销毁。当然,在需要对象时保证它们不被销毁也很重要。为了满足这些需求,Cocoa定义了一种机制—对象所有权,通过该机制您可以指定您何时需要使用一个对象,又在何时完成对该对象的使用。
为了充分理解对象所有权策略在Cocoa中是如何实现的,您还需要阅读“自动释放池”这部分的内容。
对象所有权策略
任何对象都可能拥有一个或多个所有者。只要一个对象至少还拥有一个所有者,它就会继续存在。如果一个对象没有所有者,则运行时系统会自动销毁它(参考“回收对象”)。为了确保您清楚自己何时拥有一个对象而何时不拥有对象,Cocoa设置了以下策略:
-
任何您自己创建的对象都归您所有。
您可以使用名字以“alloc”或“new”开头或名字中包含“copy”的方法(例如
alloc
,newObject
,或mutableCopy
)来“创建”一个对象。 -
您可以使用
retain
来获得一个对象的所有权。请记住,一个对象的所有者可能不止一个。拥有一个对象的所有权就表示您需要保持该对象存在。(“存取方法”更详细地讨论了这部分内容。)
-
当您不再使用您所拥有的对象时,您必须释放对这些对象的所有权。
您可以通过向一个对象发送
release
消息或autorelease
消息(在“自动释放”这一部分更详细地讨论了autorelease
)来释放您对它的所有权。因此,用Cocoa的术语来说,释放对象的所有权通常被称为“释放”(releasing)对象。 -
您不能释放非您所有的对象的所有权。
这条策略对基于GUI的Cocoa应用程序和命令行Foundation工具都适用。
请仔细思考下面的代码片段:
{ |
这个例子完全遵守上述策略。您使用alloc
方法创建了Thingamajig对象,因此,随后您在不需要该对象时对其发送了一条release
消息。当您通过Thingamajig对象获得sprockets数组时,您并没有“创建”这个数组,所以您也没有对其发送release
消息。
当您向一个对象发送autorelease
消息时,该对象的保留计数会在将来的某个阶段减1。
如果一个对象的保留计数被减为0,该对象就会被回收(请参考“回收对象”)。
重要:通常您不必显式地查询对象的保留计数是多少(参考retainCount
)。其结果往往容易对人产生误导,因为您可能不知道您感兴趣的对象由何种框架对象保留。在调试内存管理的问题上,您只需要确保您的代码遵守所有权规则。
NSObject
对象定义的autorelease
方法为后续的释放标记了接收者。通过向对象发送autorelease
消息,您亦是声明:在您发送消息的作用域之外,您不想再保留该对象。这个作用域的范围是由当前的自动释放池定义的,可参考“自动释放池”
您可以这样实现上面提到的sprockets
方法: