首页 > 代码库 > 谈谈OC的内存管理 (2013-01-08 09:28:14)

谈谈OC的内存管理 (2013-01-08 09:28:14)

苹果的内存有限,为了更好的用户体验,需要手动管理内存。从网上copy,也
一 基本原理
   Objective-C的内存管理机制与Java那种全自动的垃圾回收机制是不同的,它本质上还是C语言中的手动管理方式,只不过稍加了一些自动方法.
   1,OC采用了引用计数(retain count)对对象内存进行管理,例如,某个对象alloc了,那么这个对象的引用计数就加1,retain时加1,当对象不需要用时就需要销毁对象,释放内存,需要对象调用release方法,release会让引用计数减1,只有引用计数消失,相当于等于0,对象才会调用dealloc真正销毁这个对象.
   OC的对象在使用完成后不能自动销毁,一定要记得释放内存.
   Class *obj = [[Class alloc]init];//对象obj引用计数加1
   Class *obj2 = obj;//两个对象指向同一块内存
   [obj hello];
   [obj release];//对象被销毁
   [obj2 hello];//错误,obj2指向的内存不存在了
   [obj2 release];//[obj release]之后,obj2是个无效指针,没有内存,不能调用方法.
   注:dealloc是自动调用,一定不能手动调用.指针赋值不会使引用计数加1.
   2,OC中引入了autorelease pool(自动释放对象池),在遵守一些规则的情况下,可以自动释放对象.新生成的对象,只要调用autorelease就行了,无需再调用release.
   autorelease pool需要手动建立,在新建一个项目时,xcode会自动创建一个,NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];NSAutoreleasePool 内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象,一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去.
   NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每一个成员.如果此时数组中成员的retain count为1那么release之后,retain count为0,对象正式销毁,如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,对象依然没有被销毁,内存就会泄露,所以一定要注意内存管理规则(见下).
   注:什么情况下创建自动释放对象池?1)在多线程里面要自己创建.2)如果代码里面有大量临时变量时最好创建自动释放对象池.
   for(int i=0;i<100;i++){
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     for(int j=0;j<100000;j++){
       [NSString stringWithFormat:@"123455666"];//产生的对象是autorelease的.
     }
     [pool release];
    }
二、规则
 1 谁创建,谁释放。如果通过alloc、new或copy来创建一个对象,那么你必须调用autorelease或在使用完成时调用release,不是你创建的,就不用你去释放。
  2  除了alloc,new或copy之外的方法创建的对象在内部都被声明了autorelease。如,[UIButton buttonWithType:].
  3  谁retain,谁release,只要你调用了retain,无论这个对象是如何生成的,你都要调用release.
三、范式
 1 创建一个对象
   Class *obj = [[Class alloc] init];
  2 创建一个自动释放对象
   Class *obj = [[[Class alloc] init]autorelease];
  3 指针赋值给另一个指针
   Class *obj2 = obj1;
   [obj2 retain];
   [obj2 release];
  4 在一个函数中创建并返回对象,需要把这个对象设置为autorelease
   - (Class *)fun{
     Class *obj = [[[Class alloc] init] autorelease];
     return obj;
   }
  5 在子类的dealloc方法中调用基类的dealloc方法
   - (void)dealloc{
    ……
  [super dealloc];
   }
  对于属性里的内存机制请参考属性详细说明。
 
注:不要过度依赖retaincount,有时候内部实现并不像表面那样,计数不会换我们看到的那样,例如

MovieViewController *movie = [[MovieViewController alloc]init];

    NSLog(@"===%d",[movie.view retainCount]);//3

    NSLog(@"===%d",[movie.view retainCount]);//4

    NSLog(@"===%d",[movie.view retainCount]);//5

分享:    
 

谈谈OC的内存管理 (2013-01-08 09:28:14)