iOS中内存管理

2018-09-11  本文已影响0人  皆为序幕_

内存管理重要性

内存管理

堆和栈

//这个方法结束后,栈里的变量a、p会被回收,堆里的Person对象还会留在内存中,因为它的引用计数还是1
-(void)doSomething{
    //a:栈
    int a = 10;
    //p:栈
    //Person:堆
    Person *p = [[Person alloc]init];
}

引用计数器

OC语言使用引用计数来管理内存,每一个对象都有一个可以递增递减的计数器,如果引用这个对象,那么这个对象的引用计数递增,如果不用了,那么这个对象引用计数递减,直到引用计数为0,这个对象就可以销毁了

引用计数器的作用
引用计数器的原理
属性存取方法中的内存管理(retain、copy、assign)
- (void)setName:(NSString *)name{
    if (_name != name) {//先判断传进来的是不是新对象
        [_name release];  //把_name以前的对象release
        _name = [name retain]; //把name对象的地址赋给_name,这时name和_name共同指向同一个对象
    }
}

- (void)setName:(NSString *)name{
    if (_name != name) {
        [_name release];//把_name以前的对象release
        _name = [name copy];//把name对象的地址拷贝一份给_name
    }
}
-(void)setName:(NSString *)name{
        _name = name;    //直接赋值
}
dealloc方法
野指针和空指针

ARC

ARC是新的LLVM3.0编译器的一项特性,在工程中使用非常简单,不用再写release、retain、autorelease三个关键字。当开启ARC时,编译器将自动在代码合适的地方插入release、retain和autorelease。

循环引用

由于对象间彼此引用,无法释放,所以,循环引用会引发内存泄漏

@class Animal;
@interface Person : NSObject
@property (nonatomic,strong) Animal *animal;
@end

@class Person;
@interface Animal : NSObject
@property (nonatomic, strong) Person *person;
@end
@class Animal;
@interface Person : NSObject
@property (nonatomic,strong) Animal *animal;
@end

@class Person;
@interface Animal : NSObject
@property (nonatomic, weak) Person *person;
@end

autorelease

autoreleasepool用于存放那些需要在稍后某个时刻释放的对象,清空自动释放池时,系统会向其中的对象发送release消息

花括号定义了自动释放池的范围,左花括号开始创建,右花括号处自动释放,在此范围的末尾处,括号内的对象回收到release消息
@ autoreleasepool{

}

注:这里只是发送一次release消息,如果当时引用计数不为0,则该对象依然不会释放

autoreleasepool的原理

autorelease 实际上只是release的调用延迟了,对于每一个autorelease,系统只是把该Object放入了当前的autorelease pool中,当pool 被释放时,该pool中的所有Object会被调用release

autorelease的好处
//创建一个自动释放池
@autoreleasepool{    

   Person *p = [[Person alloc]init];
   //不用关心对象什么时候释放,只要能够访问p的地方都可以使用p
   //只要调用了autorelease,那就不用调用release
   p = [p autorelease];
   
}
//自动释放池销毁了,给自动释放池中所有的对象发送一条release消息
autorelease的注意事项
 @autoreleasepool{
     Person *p =[[[Person alloc]init] autorelease];
 }
@autoreleasepool{
   Person *p =[[[Person alloc]init] autorelease];
   //一万行代码
}
@autoreleasepool{
  for   (int i= 0;i < 99999; i ++){
     //每次调用一次就会创建一个新的对象
     //每个对象都会占用一个存储块
    Person *p =[[[Person alloc]init] autorelease];
  }
}//循环里创建对象会一直在池中,只有执行到这里才会释放
@autoreleasepool{//创建第一个自动释放池
       @autoreleasepool{//创建第二个自动释放池
           @autoreleasepool{//创建第三个自动释放池
        }//销毁第一个自动释放池
    }//销毁第二个自动释放池
}//销毁第三个自动释放池
合理利用autoreleasepool可以降低内存峰值(ARC)

把循环内的代码包裹在autoreleasepool中,那么在循环中自动释放对象就会放在这个池中,这样内存峰值就会降低(内存峰值:app在某个特定的时段内最大内存用量)

for(int i= 0;i < 99999; i ++){
    @autoreleasepool{
      Person *p =[[Person alloc]init];
      [array addObject:p];
    }
}
上一篇下一篇

猜你喜欢

热点阅读