- 基本原理
(—)为什么要进行内存管理
由于移动设备的内存有限,每个app所占的内存是及其有限的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等,因此我们需要管理内存。
不过也不是所有的对象都需要我们回收,凡是继承自NSObject的OC对象才需要我们管理,因为他们是存放在堆区中。至于一些基本的数据类型比如(整型,浮点型,枚举,结构图,布尔)还有一些局部变量是存放在栈空间中的,当代码块结束的时候,他们也就自动回收了!
(二)如何管理内存
在Ios5之前,都是需要手动管理内存的也就是MRC,原理很简单,通过自动引用计数控制,当创建一个对象或者想拥有一个对象,那么该对象就会发送retain(引用计数+1)消息,当不想拥有这个对象,该对象就会发送release(引用计数-1)消息,直到当一个对象的引用计数为0的时候,就会调用对象的dealloc方法,这时候系统就知道该对象要被回收!
不过苹果爸爸为了减轻开发者的负担,在Ios5之后,给广大Ios开发者传来了好消息,推出了ARC(Automatic Reference Counting),全称为自动引用计数,也就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。
(三)内存管理代码规范
- 只要调用了alloc,就必须有release(autorelease)
- set方法的代码规范
基本数据类型:直接赋值
- (void)setHeight:(CGFloat)height{
_height = height;
}
OC对象类型:直接赋值
- (void)setBook:(Book *)book{
if (_book!=book) {//先判断是不是新传进来的对象
[_book release];//对旧对象做一次release
_book = [book retain];//对新对象做一次retain
}
}
- dealloc方法的代码规范
- (void)dealloc{// 临终遗言
NSLog(@"人被释放");
[_book release];// 对拥有的对象做一次release
[super dealloc];//MRC一定要调用
}
(四) @property的参数
(1)内存管理相关参数
Retain:对对象release旧值,retain新值(适用于OC对象类型)
Assign:直接赋值(默认,适用于非oc对象类型)
Copy:release旧值,copy新值
(2)是否要生成set方法(若为只读属性,则不生成)
Readonly:只读,只会生成getter的声明和实现
Readwrite:默认的,同时生成setter和getter的声明和实现
(3)多线程管理(苹果在一定程度上屏蔽了多线程操作)
Nonatomic:高性能,一般使用这个,苹果推荐使用这个
Atomic:低性能
(4)Set和get方法的名称
- 修改set和get方法的名称,主要用于布尔类型。因为返回布尔类型的方法名一般以is开头,修改名称一般用在布尔类型中的getter。
@propery(setter=setAbc,getter=isRich) BOOL rich;
BOOL b=p.isRich;// 调用
(五) 内存管理中的循环引用问题以及解决
案例:每个人有一张身份证,每张身份证对应一个人,不能使用#import的方式相互包含,这就形成了循环引用。
新的关键字:@class 类名;——解决循环引用问题,提高性能
@class仅仅告诉编译器,在进行编译的时候把后面的名字作为一个类来处理。
@class的作用
- 声明一个类,告诉编译器某个名称是一个类
开发中引用一个类的规范
在.h文件中使用@class来声明类
在.m文件中真正要使用到的时候,使用#import来包含类中的所有东西
两端循环引用的解决方法
一端使用retain,一端使用assign(使用assign的在dealloc方法中也不用再release)
(六)ARC内存管理原理
-
ARC判断准则
只要没有强指针指向对象,该对象就会被释放!另外要强调的是由编译器来检测。 -
指针分类
强指针:默认的情况下所有对象创建的指针都是强指针,__strong关键字表示,在修饰property属性中相当于retain(适用于oc对象类型)!
弱指针:__weak关键字表示,当对象被回收的时候__weak会被清空nil,不然会有野指针错误,这是系统帮忙做好的。在修饰property属性中相当于assign(适用于oc对象类型)。 -
注意事项
让程序兼容ARC和非ARC部分。转变为非ARC -fno-objc-arc 转变为ARC的, -f-objc-arc 。
ARC也需要考虑循环引用问题:一端使用strong,另一端使用weak。
assign:修饰基本数据类型,不适用于oc对象。