objc内存管理

http://blog.sina.com.cn/s/blog_538ee4a70100o9o2.html

如果要从事Leopard或更高版本的MacOS程序开发使用Objective-C 2.0的垃圾回收机制,若要从事旧版本MacOSiPhone开发则要全部阅读本章内容

一、对象生命周期

程序中的对象由生命周期,其周期包括:诞生(allocnew)、生存(接受消息和执行操作)、                                                                               交友(借助方法的组合和参数)和消亡(被释放)

 

1、引用计数

Cocoa采用了一种称为引用计数(保留计数)的技术:

(1)每个对象有一个与之相关联的整数,称为他的引用计数器或保留计数器

(2)当代码访问某个对象时,改代码将该对象保留计数器值增加1,表示我要访问该对象

(3)当代码结束对象访问时,将对象的保留计数器值减1,表示不再访问该对象

(4)在保留计数器值为0时,表示不再有代码访问该对象,对象将被销毁,启动垃圾回收机制

 

使用方法:

(1)使用allocnew或通过copy消息(生成接收对象副本)创建对象时对象的保留计数器数值被设置为1

(2)要增加计数器值,可以调用对象的retain方法

-(id) retain; 返回一个id类型值。

通过这种方式,可以嵌套执行带有其他方法参数的保留调用,增加对象的保留计数器值并要求对象完成某种操作

例:[[car retain] setTire : tire anIndex : 2]    

表示要求car对象将其保留计数器值加1并执行setTire操作

 

(3)要减少对象的保留计数器值,调用对象的release方法

-(void) release;

(4)当对象因保留计数器归0将被销毁时,Objective-C自动调用dealloc方法,此方法可重写,但不要直接调用,而是要让Objective-C自动调用

-(unsigned) retainCount;

(5)获得当前保留计数器的当前值,可以调用retainCount方法

 

2、对象所有权object ownership

如果一个对象具有指向其他对象的实际变量,则称该对象拥有这些对象

 

3、访问方法中对象的保留和释放

-(void) setEngine : (Engine *) newEngine

{

         [newEngine  retain];//增加newEngine的保留计数器

         [engine  release];//减少engine的保留计数器

         engine = newEngine;//engine保存为newEngine

}

二、自动释放

1、所有对象全部入池

Cocoa中有一个自动释放池(autorelease  pool),他是一个存放实体的池(集合),这些实体可能是对象,能被自动释放

NSObject类提供了一个autorelease方法:-(id) autorelease;

该方法预先设定了一条在将来某个时间发送的release方法,其返回值是接收消息的对象

当给一个对象发送autorelease方法时,实际上是将该对象添加到NSAutoreleasePool中,自动释放池被销毁时,回想该池中的所有对象发送release消息

举例代码:

         -(NSString  *)description

         {

                   NSString  *description;

                   description = [[NSString alloc] initWithFormat : @"I am %d years old",4];

                   return ([desciption autorelease]);

         }

description方法首先创建了一个新的字符串对象,然后自动释放,最后将其返回给调用的函数

 

2、自动释放池的销毁时间

Cocoa定期自动创建和销毁自动释放池,通常是在处理完当前事件以后执行操作。

我们可以使用任意多的自动释放对象,当不需要他们时,自动释放池将自动为你清理这些对象

NSAutoreleasePool  *pool;

pool = [[NSAutoreleasePool alloc] init];

……

[pool release];

TipXcode自动生成的另一种销毁自动释放池-drain方法只是清空自动释放池而不销毁它,这种方法只适用于10.4以及更高版本,使用-release方法适用于全部版本

 

3、自动释放池的工作过程

举例代码:

         int main(int argc, const char *argv[])

         {

                   NSAutoreleasePool *pool;                          //首先创建一个自动释放池

                   pool = [[NSAutoreleasePool alloc] init];

 

                   RetainTracker *tracker;                              //新的tracker对象被创建

                   tracker = [RetainTracker new];                 //保留计数器值为1

 

                   [tracker retain];                                             //使保留计数器值增加到2

                   [tracker autorelease];                                 //将对象添加到自动释放池,值仍为2

                   [tracker release];                                          //释放对象,保留计数器值为1,对象仍存在

 

                   NSLog(@"releasing pool");

                   [pool release]; //销毁自动释放池,NSAutoreleasePool是一个普通对象遵从相同的内                                                存管理规则,因为创建时发送了alloc消息其保留计数器为1,执行                                                        release后变为0,自动释放池将被销毁

                   return(0);                   //函数返回0表示全部操作成功执行

         }

 

三、Cocaoa内存管理规则

规则:

(1)    当使用newalloccopy方法创建一个对象时,该对象的保留计数器值为1

         当不再使用该对象时,向该对象发送releaseautorelease消息,该对象将被销毁

(2)    当对象被设置为自动释放,我们不需要执行任何操作来确保该对象被清理

         如果要在一段时间内拥有该对象,则需要保留它并确保操作完成时释放他

(3)    如果保留了某个对象,需要释放或自动释放该对象,需保持retainrelease方法的使   用次数相等

 

1、临时对象

使用任何其他方法(非newalloc或者copy)获得对象不需要关心如何销毁该对象

举例代码:

         NSMutableArray  *array;

         array = [NSMutableArray arrayWithCapacity : 17];

arrayWithCapacity不属于allocnewcopy方法,使用该方法返回的对象保留计数器值为1并且已经被设置为自动施放

举例代码:

         NSColor *color;

         color = [NSColor blueColor];

blueColor返回一个全局单例对象,这个对象永远不会被销毁

 

2、拥有对象

(1)使用newalloccopy方法获得对象,手动释放

举例代码:

         -(void) doStuff

         {

                   flonkArray = [NSMutableArray new];

         }

         -(void) dealloc

         {

                   [flonkArray release];

                   [super dealloc];

         }

(2)使用非newalloccopy方法获得对象,自动释放

         -(void) doStuff

         {

                   flonkArray = [NSMutableArray new];

                   [flonkArray retain];           //唯一的不同点

         }

         -(void) dealloc

         {

                   [flonkArray release];

                   [super dealloc];

         }

 

(3)再循环中清空自动释放池

举例代码:

         NSAutoreleasePool *pool;

         pool = [[NSAutorelease alloc] init];

         int i;

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

                   id object = [someArray  objectAtIndex : 1];

                   NSString  *desc = [object description];

                   if(i % 1000 == 0){                         //每循环1000次时清理一次自动释放池,如果不这样                                [pool release];                    //做将会在1百万次循环时清理内存,程序将非常慢

                            pool = [[NSAutorelease alloc] init];

                   }

         }

         [pool release];

 

3、垃圾回收

Objective-C 2.0引入了自动内存管理机制,也称垃圾回收

 

启动垃圾回收功能:转到项目信息窗口的Build选项卡,然后选择Required [-fobjc-gc-only]选项即可

Tip: -fobjc-gc是为了使代码既支持垃圾回收又支持对象的保留和释放

 

启用垃圾回收以后,内存管理命令全部变成了空操作指令,不执行任何操作

 

posted @ 2011-08-24 17:32  痴人指路  阅读(244)  评论(0编辑  收藏  举报