内存管理
2019-02-28 本文已影响0人
陌巷先森
一、管理对象
iOS中的对象一般有两种:
- 引用类型:任何继承了NSObject类的对象
- 值类型:比如int、char、float、double、struct、enum等基本数据类型
引用类型的对象都储存在系统的堆里面,一般由程序员分配释放,若程序员不释放,程序结束后由系统回收,分配方式类似于链表;非OC对象一般放在系统的栈里面,由操作系统自动分配释放,一般存放函数的参数值,局部变量的值等。
二、内存管理模型
内存管理模型有以下三种:
- 自动垃圾收集(OS X)
- 手工引用计数和自动释放池(MRC)
- 自动引用计数(ARC)
三、引用计数(Reference Count)
苹果采用引用计数的方式来管理对象,当对象的引用计数为0后,表示对象没有被任何代码引用,此时对象将会被释放。
- 当对象被创建(通过alloc、new或copy等方法)时,其引用计数初始值为1
- 给对象发送retain消息,其引用计数加1
- 给对象发送release消息,其引用计数减1
- 当引用计数为0时,系统给对象发送dealloc消息,销毁对象
实例代码
Car *car = [[Car alloc] init];
NSLog(@"初始引用计数--%ld",car.retainCount);
[car retain];
NSLog(@"retain后引用计数--%ld",car.retainCount);
[car release];
NSLog(@"release后引用计数--%ld",car.retainCount);
[car release];
//当对象销毁后需要将指向对象的指针设为nil,避免产生野指针
car = nil;
打印如下:
HCCiOSDemo[1333:826830] 初始引用计数--1
HCCiOSDemo[1333:826830] retain后引用计数--2
HCCiOSDemo[1333:826830] release后引用计数--1
HCCiOSDemo[1333:826830] car对象被销毁了
三、MRC手动管理内存(Manual Reference Counting)
autorealease:将对象放入自动释放池中,当自动释放池销毁时会对自动释放池中的对象都进行一次realease操作,autorelease方法会返回对象本身,且调用完autorelease方法后,对象的计数不变。
自动释放池有两种创建方式
- 使用
NSAutoreleasePool
创建 - 使用
@autoreleasepool
创建
四、ARC自动管理内存(Automatic Reference Counting)
从OS X Lion和iOS 5开始,苹果引入了ARC机制,使用ARC后,系统会检测出何时需要保持对象,何时需要自动释放对象,编译器会管理好对象的内存,会在合适的地方插入retain,release和autorelease。
ARC提供四种修饰符,分别是__strong, __weak, __autoreleasing, __unsafe_unretained。
__strong
强引用,持有所指向对象的所有权,无修饰符情况下的默认值。
id __strong obj = [[NSObject alloc] init];
NSLog(@"obj引用计数--%@",[obj valueForKey:@"retainCount"]);
id __strong newObj = obj;
NSLog(@"obj引用计数--%@",[obj valueForKey:@"retainCount"]);
//将一个对象赋值给另外一个对象时,表示newObj的指针与obj的指针指向同一个NSObject对象,会将该对象的引用计数器加1
打印如下:
HCCiOSDemo[1753:1271122] obj引用计数--1
HCCiOSDemo[1753:1271122] obj引用计数--2
__weak
弱引用,不持有所指向对象的所有权,引用指向的对象内存被回收之后,引用本身会置nil,避免野指针。
id __weak obj1 = [[NSObject alloc] init];
NSLog(@"obj1引用计数--%@",[obj1 valueForKey:@"retainCount"]);
//__weak修饰的指针没有引起对象的引用计数器变化,因此在生成之后马上就会被释放
打印如下:
HCCiOSDemo[1831:1418225] obj1引用计数--(null)
__autoreleasing
自动释放对象的引用,一般用于传递参数
__unsafe_unretained
__unsafe_unretained作用需要和weak进行对比,它也不会引起对象的内部引用计数器的变化,但是,当其指向的对象被销毁时__unsafr_unretained修饰的指针不会置为nil。而且一般__unsafe_unretained就和它的名字一样是不安全,它不纳入ARC的内存管理
参考:完整项目资料下载