一、内存管理的原因
移动设备的内存极其有限,每个app所能占用的内存是有限制的。当app所占用的内存较多时,系统会发出内存警告,甚至app占用内存过大时,系统可能会强制关闭app,造成闪退现象,影响用户体验。这时有必要回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等。
本质原因:因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对象已经没有指针指向,但依然存在于内存中,造成内存泄露。
二、内存管理
所谓内存管理,就是对内存进行管理,涉及的操作有:a、分配内存 :比如创建一个对象, 会增加内存占用。 b、清除内存 :比如销毁一个对象, 能减小内存占用。
内存管理的管理范围: a、任何继承了NSObject的对象。b、对其他非对象类型无效如int,char,float,double,struct,enum等
三、引用计数器
每个OC对象内部都有4个字节的存储空间来存放引用计数器。
1、引用计数器的作用:简单来说,可以理解为:引用计数器表示有多少人正在使用这个对象。
a、当对象的引用计数器为0时, 对象占用的内存就会被系统回收。如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )
b、任何一个对象,刚生下来的时候,引用计数器都为1。当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1。
2、引用计数器的常见操作
a、给对象发送一条retain消息, 可以使引用计数器值+1(retain方法返回对象本身)
b、给对象发送一条release消息, 可以使引用计数器值-1
c、给对象发送retainCount消息, 可以获得当前的引用计数器值
注意: release并不代表销毁\回收对象, 仅仅是计数器-1
四、对象的销毁(dealloc)
1、当一个对象的引用计数器值为0时,这个对象即将被销毁,其占用的内存被系统回收,系统会自动给对象发送一条dealloc消息。(因此, 从dealloc方法有没有被调用,就可以判断出对象是否被销毁)
2、dealloc方法的重写
a、一般会重写dealloc方法, 在这里释放相关资源,dealloc就是对象的遗言。
b、一旦重写了dealloc方法, 就必须调用[superdealloc],并且放在最后面调用。
3、使用注意:a、不能直接调用dealloc方法。b、一旦对象被回收了,它占用的内存就不再可用,坚持使用会导致程序崩溃(野指针错误)
4、野指针/空指针
六、@property参数
a、僵尸对象:已经被销毁的对象,即所占内存已经被回收的对象。
b、野指针:指向僵尸对象(不可用内存)的指针。给野指针发消息会报EXC_BAD_ACCESS错误。
c、空指针:没有指向存储空间的指针,即里面存的是nil,也就是。
为了避免野指针错误的常见办法:在对象被销毁之后,将指向对象的指针变为空指针。
五、内存管理原则
苹果官方规定的内存管理原则:
1、谁创建谁release : 如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease。
2、谁retain谁release :只要你调用了retain,就必须调用一次release。
简单来说:有加就有减。曾经让对象的计数器+1,就必须在最后让对象计数器-1。
3、多对象的内存管理
如果对多个对象进行内存管理,并且对象之间是有联系的,比如,某一个对象中又包含另一个对象的属性, 那么管理就会变得比较复杂。
管理规律:a、只要还有人在用某个对象,那么这个对象就不会被回收。2、只要你想用这个对象,就让对象的计数器+1。3、当你不再使用这个对象时,就让对象的计数器-1。
1、内存管理相关参数
Retain:对对象release旧值,retain新值(适用于OC对象类型)
Assign:直接赋值(默认,适用于非oc对象类型)
Copy:release旧值,copy新值(一般用于NSString * )
2、控制是否要生成set方法
Readonly:只读,只会生成getter的声明和实现
Readwrite:默认的,同时生成setter和getter的声明和实现
3、多线程管理
苹果在一定程度上屏蔽了多线程操作
Nonatomic:高性能,一般使用这个
Atomic:低性能
七、Autorelease(缓冲池)
1、基本用法
a、会将对象放到一个自动释放池中。
b、当自动释放池被销毁时,会对池子里的所有对象做一次release。
c、会返回对象本身。
d、调用完autorelease方法后,对象的计数器不受影响(销毁时影响)。
2、好处:a、不需要再关心对象释放的时间。b、不需要再关心什么时候调用release。
使用注意:a、占用内存较大的对象,不要随便使用autorelease,应该使用release来精确控制。b、占用内存较小的对象使用autorelease,没有太大的影响。
3、Autorelease注意
a、系统自带的方法中,如果不包含alloc new copy等,则这些方法返回的对象都是autorelease的,如[NSDate date];
b、开发中经常会写一些类方法来快速创建一个autorelease对象,创建对象时不要直接使用类名,而是使用self。
八、ARC内存管理机制
1、ARC的判断准则:只要没有强指针指向对象,对象就会被释放。
2、指针分类:a、强指针:默认的情况下,所有的指针都是强指针,关键字strong。b、弱指针:_ _weak关键字修饰的指针
声明一个弱指针如下:_ _weak Person *p;
ARC中,只要弱指针指向的对象不在了,就直接把弱指针做清空操作。
ARC中在property处不再使用retain,而是使用strong,在dealloc中不需要再[super dealloc]。
@property(nonatomic,strong)Dog *dog;// 意味着生成的成员变量_dog是一个强指针,相当于以前的retain。
如果换成是弱指针,则换成weak,不需要加_ _。
3、ARC的特点总结:a、不允许调用release,retain,retainCount。b、不允许重写dealloc,但是不允许调用[super dealloc]。 @property的参数:
Strong:相当于原来的retain(适用于OC对象类型),成员变量是强指针。
Weak:相当于原来的assign,(适用于oc对象类型),成员变量是弱指针。
Assign:适用于非OC对象类型(基础类型)。
提示:下图为关闭ARC机制图解