一 内存管理介绍
1.内存管理的重要:应用的运行都需要内存 ,如果合理管理内存 会造成应用程序崩溃 ,也就是闪退(crash)影响我们使用.
2.内存管理的问题:
① 内存溢出:IOS 给每个程序运行都设定了 一定的内存,如果超过了这个限定,便是溢出,造成 Crash;
②野指针:指针指向了 僵尸对象°,
注:僵尸对象:对象内存空间已经被回收,但指针仍操作这个空间;
3.内存管理的方式:
①垃圾回收: gc (Garbage Collector) 程序员只需要开辟内存空间,不需要⽤用代码显⽰示地释放,系统来判断哪些空间不再被使⽤用,并回收这些内存空间,以便再次分配。整个回收的过程不需要写任何代码,由系统⾃自动完成垃圾回收。Java开发中⼀一直使⽤用的就是垃圾回收技术。
缺点: gc 有不稳定性,回收无规律可循,不会立刻回收,也可能到结束也不会回收,所以在 Java 开发中会加入一个指令 强制 gc 运行;
②人工引用计数 :MRC (Maual Reference Count) 有程序员自己通过引用计数去管理释放和开辟空间 相对 gc 灵活, 可在需要时释放
缺点:因为是通过程序代码,所以对程序员的要求较高,需熟练掌握内存管理机制;
③自动引用计数: ARC( Automatic Reference Count) 可以认为是 IOS5.0的编译器特征,它允许用户开辟空间,但是不需要释放,编译器会帮程序员默认加了释放代码 但这个不是垃圾回收 本质还是 MRC
缺点: 不及时 ;
-------------------------------------------------------Nyx------------------------------------------------------------
二 内存管理机制
1.引用计数器: retainCount 占4个字节, 占字符 %lu,
2.定义:当一个新的引⽤指向对象时,引用计数器就递增,当去掉一个引用时,引⽤计数就递减。当引⽤计数到零时,该对象就将释放占有的资源。
3.影响应用的方法:
①递增,:(alloc; copy; new; retain; ) 将引用计数+1
{
<1> alloc : 开辟空间,并将开辟空间的引用计数由0 -->1,
例: Person*person = [[Personalloc ] init];/ /这时候引用计数变成了 1
<2> retain :引用计数加1 在之前的引用 计数上加一个,如果之前是1 那么retain 之后 就是2;
例:
NSLog(@"%lu",person.retainCount);
在控制台中输出为2.
例:
Person *person7 = [Personnew];
person7.name = @"lei";
NSLog(@"%lu",person7.retainCount);
}
Copy 比较特殊 下面会单独写一个
② 递减:(release,autorelease) 就是对 引用计数- 1
{
<1> release : 对一个对象的计数器 - 1 减到0 对象就会从内存中释放掉 (dealloc);
<2>@autorelease:{
有大括号 才是完整的 这一个自动释放池 如果想用 又想快速释放 可以讲@ autorelease {}写在 for 循环的第一层,
}
第二种自动释放池
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
Person *person3= [[Personalloc]init ];
person3.name = @"wang";
[pool release];
注:紫色的两行构成一个完整的释放池 ,不过不推荐用 ,第一种更方便
<3> dealloc :(继承⾃自⽗父类的⽅方法,当对象引⽤计数为0的时候,由对象⾃动调⽤用)
我们为了看出 是否到0 可以在. m 里面写一个代码 当计数为0时 就跳入这个代码
例: -(void)dealloc{
NSLog(@“%@被销毁了”,self);
[super dealloc]; // 这个代码 是必须要有额 而且在大括号代码里的最下面
}
2.autorelease 和 release 的区别
1.autorelease 相比 release 也是对引用计数器 执行-1操作,不过 autorelease 不是立即释放-1 而是在未来的某个时间
2.autorelease 的实质: 对一个对象使用 autorelease 操作,这个对象的引用计数不会立即-1,对象会被放在自动释放池里面,等这个池子结束之后,会对对象的引用计数依次-1
-------------------------------------------------------Nyx------------------------------------------------------------
三 Copy :
1.定义把某⼀内存区域的内容拷⻉一份,拷⻉到新的内存空间⾥里去,被拷贝区域的引⽤用计数不变,新的内存区域的引⽤用计数为1
注意:对象使用 copy 的前提 ,这个类遵循了 NSCopying 协议 而且必须实现协议内的方法
例:在. h 文件中
@interface Person : NSObject <NSCopying> // Object 后面 跟了 <NSCopying>, 这就协议遵守好了
① 浅拷贝: 单纯拷贝指针(也就是地址,打出来的是 一串数字)
-(id)copyWithZone:(NSZone *)zone{
return [self retain];
}
② 深拷贝: 会从新开辟一个空间 复制原来的内容,返回一个新的对象,但是所占空间大小相同, 可以理解为 A 被完整复制 ,但是换了地址 ,
-(id)copyWithZone:(NSZone *)zone{
Person *p = [[Person allocWithZone:zone]init];
p.name =@"123";
return p;
}
-------------------------------------------------------Nyx------------------------------------------------------------
1.谁 alloc 谁 release ,用了 就释放 哪怕就一次;
2. 为了方便可以定义带参宏
例:#define RELEASE_SAFE(_point) [_point release];_point = nil;
宏 下面要用的新名字 要代替的方法格式,用分号隔开
3.使用了alloc、retain或者copy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等。
4. 如果是像生成自己的副本 ,对象可以使用 copy ,但是一定要遵守 NSCopying 的 协议哟 \(≧▽≦)/
5.设置内存管理之前要记得将系统的 ARC 关闭