第17章 内存管理

对于内存管理这个主题的关注贯穿全书。现在,应该已经明白什么时候由你负责释放对象,以及什么时候不由你释放。虽然本书中所有的例子都很小,但我们仍然强调内存管理的重要性,以便讲述好的程序设计习惯,并开发无内存泄漏的程序。

根据编写的应用程序类型,明智的内存使用可能很重要。例如,假如编写一个交互式的制图应用程序,这个程序在执行过程中创建很多对象,如果不够小心,那么你的程序在运行过程中可能会不断地消耗越来越多的内存资源。在这种情况下,明智地管理这些资源并在不再需要它们时释放就成为你的责任。这就意味着,在程序执行的过程中而不是等到程序结束时释放资源。

本章将更详细地讲解Foundation的内存分配策略。这涉及到对自动释放池的详细讨论和保持对象(retaining object)的概念。还将学习对象的引用计数。最后,我们会介绍称为垃圾回收的机制,这可缓解因保留对象并在使用完后释放这些对象的压力。然而你会看到,不能为iPhone应用程序使用垃圾回收,所以你仍需要理解本书中介绍的内存管理技术(本章会详细介绍这些内容)。

17.1 自动释放池

通过本书第二部分的程序例子,你已经熟悉了自动释放池。在处理Foundation程序时,为了使用Foundation对象,必须设置自己的池。系统使用这个池来跟踪对象,以便以后释放。在应用程序中,可以通过调用来建立这个池,如下所示:


NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];


建立了自动释放池之后,Foundation将自动为这个池添加特定的数组、字符串、字典以及其他对象。使用完该池时,可以发送drain消息来释放它使用的内存:


[pool drain];


任何标记为自动释放并因此添加到池中的对象,将在池本身被释放的同时也自动释放,自动释放池的名称就是由此而来的。事实上,程序中可以有多个自动释放池,并且它们还可以是嵌套的。

如果你的程序产生了大量的临时对象(这种情况在执行循环中的代码时经常发生),可能需要在程序中创建多重自动释放池。例如,代码片段


NSAutoreleasePool*tempPool;

……

for(i=0;i<n;++i){

tempPool=[[NSAutoReleasePool alloc]init];

……//lots of work with temporary objects here

[tempPool drain];

}


说明了如何创建几个自动释放池来释放由for循环的每一次迭代而产生的临时对象。

应该注意到自动释放池并不包含实际的对象本身,仅仅是对释放池时要释放的对象的引用。

通过向当前的自动释放池发送一条autorelease消息,可以将一个对象添加到其中,以便以后释放:


[myFraction autorelease];


然后,系统将myFraction添加到自动释放池中以便将来自动释放。你将看到,autorelease方法对于在某个方法内标记对象以便以后进行处理是非常有用的。