一.OC内存管理机制
1.内存管理
OC内存管理的范围是所有继承自NSObbject的对象。对基本数据类型是无效的。(基本数据类型的对象由系统自动回收)
OC内存管理是是使用引用计数法则,当一个对象被创建时便会有retainCount(引用计数器)这个属性。
2.引用计数器
每个OC对象都有一个8位的引用计数器,当使用alloc,new或者copy的来创建一个新对象的时候,新对象的引用计数默认被设置为1
当一个对象的引用计数为0时,这个对象便会被系统回收
对象的引用计数不为0时,在程序运行中,它所占用的内存时不会被回收的,直到程序运行结束。
3.引用计数的操作
给对象发送retain消息时,引用计数加1
给对象发送release消息时,引用计数减1
给对象发送retainCount消息时,可以获得当前的引用计数值
4.对象销毁
当一个对象的引用计数为 0时,它所占用的内存便会被系统回收。对象销毁一般调用的是dealloc方法。
野指针
这里需要注意的是避免野指针的出现,当对象被回收那么他对应的内存便不能再使用,强行使用的话会导致程序崩溃。
而野指针指的就是那些指向僵尸对象(不可用内存)的指针。
为了避免野指针的出现一般在对象被回收之后,将指设置为空指针。
如:
Person *p = [[Person alloc] init];
[p release];
//当实例对象被释放后,不能给它发送任何一条消息。
p = nil;
二.内存管理方式
1.内存管理的原则
内存管理的黄金法则,如果一个对一个对象使用了alloc,copy,retain,那么必须使用的相应的relese或者autorelease进行释放。(即谁创建谁释放)
2.set方法管理内存
如果一个类中有一个OC对象的成员变量,则这个类必须负责这个成员变量相关的内存。
例如一个人拥有一辆车,那么在人的对象被销毁之前必须先将车的引用计数器减一。
- (void)setCar:(Car *)car {
//判断是否自我赋值
if (_car != car)
{
//对正在使用的车做一次release
[_car release];
_car = [car retain];
}
}
- (void)dealloc {
NSLog(@“Person被释放");
//在人被销毁之前,先对车做一次release
[_car release];
[super dealloc];
}
3.@property参数
@property可以自动生成setter方法和getter方法的声明和实现,除此之外@property还可以加入一些参数来对自动生成的setter方法和getter进行限定。
比如: @property(retain,readonly) int a;
三.循环引用
循环引用指的是两个对象相互retain,导致两个永远无法释放。
B.h中
@property (nonatomic,retain) A;
A.h中
@property (nonatomic,retain) B;
这样就会造成循环引用。
解决方案,一端用assign,另一端用retain
四.autorelease方法
给对象发送一条autorelease消息之后,对象被放入到一个自动释放池中
当自动释放池销毁时,会给释放池中调用过autorelease的对象发送一条release消息
autorelease只是延迟了对release的调用,并不会改变对象本身的计数器。
自动释放池的创建
@autoreleasepool {
在此加入对象
}
五.ARC
ARC是自动管理内存的,在ARC中有强指针和弱指针分别用(_strong和_weak修饰),当没有强指针指向对象时,就会释放改对象。
循环引用,在ARC中也存在循环引用,
如:
在B.h中
@property (nonatomic,strong) A;
在A.h中
@property (nonatomic,strong) B;
解决方式是一个用weak修饰,一个用strong修饰
一个项目中可以兼容MRC和ARC。