黑马程序员---OC基础---内存管理(MRC、ARC)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、内存管理概述

由于移动设备的内存及其有限,每个app所占用的内存也是有限制的,当app所占内存过大时,可能会造成闪退现象,影响用户体验。因此我们在做程序设计时,要对内存的分配与回收进行管理

1.内存管理范围:所有继承了NSObject的对象(所有OC对象、对象类型),对基本数据类型无效

2.只对OC对象进行内存管理的原因:非OC对象一般放在栈里面,而系统会自动回收栈内存,不需要我们管理。而OC对象是存放在堆空间的,系统不能自己回收内存,因此需要人为地对其进行管理

二、MRC

1.引用计数器:每个 OC对象都有自己的引用计数器,它是一个整数,表示对象被引用的次数,每个对象刚创建时,引用计数器默认为1,当它等于0时,对象占用内存被系统回收
2.引用计数器常见操作:
1)给对象发送一条retain消息,使引用计数器加1
Person  *p = [[Person alloc]init];
[p retain];
2) 给对象发送一条release消息,使引用计数器减1
Person  *p = [[Person alloc]init];
[p release];
3) 给对象发送一条retainCount消息,获得当前引用计数器值
[p  retainCount];
3.对象的销毁
1)当引用计数器为0时,对象内存被回收
2)对象销毁时,系统自动向对象发送一条dealloc消息,不能人为调用
3)一般会重写dealloc方法,释放相关资源
4)一旦重写dealloc,必须调用[super dealloc]
-(void)dealloc{
    [super dealloc];
}
4.野指针、空指针、僵尸对象
1)僵尸对象:已经被销毁的对象
2)野指针:指向僵尸对象的指针
3)空指针:没有指向任何储存空间的指针
4)野指针防止方法:对象销毁后,将该指针变为空指针,p=nil
5.autorelease
用法&作用:
1)将对象放到自动释放池中(releasepool)
2)当池被销毁,所有对象release一次
3)返回对象本身
4)调用autorelease后,对象引用计数器不变
好处:
1)不用关心对象释放时间
2)不用管何时用release
autoreleasepool{
    Person *p =[ [Person alloc]init];
    [p autorelease];
}
6.多对象内存管理
当对象调用另外一个对象时,给后者对象引用计数器加1,当不调用了,给后者引用计数器减1
Book  *b = [[Book alloc]init];
    [b retain];
Person  *p = [[Person alloc]init];
    [p retain];
    p.book = b;
    [b retain];

[p release];
[b release];
[b release];
1)set方法的内存管理
当主调对象用set方法更换调用的对象后,前一个被调对象的内存未被释放,所以要重写set方法
-(void)setBook:(Book *)book{
    if (book!=_book){        //判断是否有新的调用
        [_book release];      //若有新调用,原来被调对象release,新被调对象retain
        _book = [book retain];
    }
}
2)多对象dealloc方法
若成员变量中有OC对象类,则dealloc方法需要对其release一次
-(void)dealloc{
    [_book release]; 
    [super dealloc];
}
3)内存管理原则
a.谁创建谁release:如通过alloc、new或者copy创建一个新对象,那么你就必须调用release或autorelease
b.谁retain谁release:一次retain必须对应一次release
4)@property参数
a.控制set方法的内存管理:
----retain:release旧值,retain新值
----assign:直接赋值,不作内存管理(默认)
----copy:release旧值,copy新值(一般用于NSString*)
b.控制是否需要生成set方法
----readwrite:同时生成set和get方法(默认)
----readonly:只生成get方法
c.多线程管理
----atomic:性能低(默认,Mac开发建议使用)
----nonatomic:性能高(iOS开发建议使用)
@property(nonatomic,retain) Book *b;
@property(nonatomic,assign) int age;
5)对象循环调用问题
当对象循环调用时,程序退出后,两个对象空间都没释放,造成内存泄露。
解决方法:一个对象的@property使用retain,另一个使用assign
//对象Person
@property(nonatomic,retain)Book *book;
//对象Book
@property(nonatomic,assign)Person *p;

三、ARC

1.概述:ARC全称Automatic Reference Counting(自动引用计数器),是iOS5后新增加的特性。它是编译器特性,而不是运行时特性
2.实现细节:编译器会在适当时候插入retain、release、autorelease,即编译器自动生成内存管理代码
3.优点:
1)完全消除了手动内存管理的烦恼
2)基本上可以避免内存泄露
3)有时还能更加快速,因为编译器还可以执行某些优化
4.判断准则:只要没有强指针指向对象,对象就会被释放,指针销毁
----强指针:所有普通指针都为强指针(系统默认)
----弱指针:用“__weak”修饰的指针
__weak Person *p = [Person new];
这里的指针p就为弱指针,Person对象没有强指针指向它,立即被释放
5.特点:
1)不允许调用release、retain和retainCount
2)允许重写dealloc方法,但不允许调用[super dealloc]
3)@property参数
----strong:强指针,相当于MRC中retain
----weak:弱指针,相当于MRC中assign
----assign:同MRC中assign,用于非OC对象
6.ARC中循环引用问题:解决方法类似MRC中循环引用问题,一个封装@property用strong,另一个用weak
//Person对象
@property(nonatomic,strong)Book *b;
//Book对象
@property(nonatomic.weak)Person *p;


你可能感兴趣的:(黑马)