Effective Objective-C - 内存管理
前言
Effective Objective C 读书笔记 - 内存管理
笔记
理解引用计数
引用关系有一个引用树,在iOS中,这个根引用对象是UIApplication
调用alloc,引用计数加1,表示该对象想存活下去
即使对象的引用计数为0,其占用的内存已经被dealloc了,但是注意:这个时候它的内存只是放回了“可用内存池”,里面的数据不会立即被覆盖
记住一点:在MRC中,将指针指向对象是不会增加reference count的,必须手动加1
看看下面的MRC代码:
1
2
3
4
5
6
7- (NSString *)stringValue {
NSString *str = [[NSString alloc]] initWithFormat:@"vanney"; // 1
return str;
}
NSString *str = [self stringValue];
[str retain]; // 2上面的代码在注释1,和注释2处分别增加了一次reference count,但是讲道理这个时候只需要一个reference count就可以了,所以会出现一些些小问题。这就需要Auto Release Pool了
1
2
3
4
5
6
7- (NSString *)stringValue {
NSString *str = [[NSString alloc]] initWithFormat:@"vanney";
return [str autorelease];
}
NSString *str = [self stringValue];
[str retain];注意retain cycle,也就是相互引用
以ARC简化引用计数
- 代码中不再需要写:
retain
和release
方法,但是这两个方法实际上还是执行了的,他们由ARC帮你执行 - ARC中调用这些方法绕过了消息转发,直接调用底层的C函数,更加快速
- 如果autorelease后面跟上的是retain,那么ARC可以优化这两个操作(因为这两个操作加在一起,什么也没做…)。这种优化通过设置标志位来实现,具体的看书~
- CoreFoundation的内容不适合ARC
在dealloc方法中只释放引用并解除监听
- delloc方法在对象reference count降到0时,会被调用
- 因为ARC会帮你生成释放对象所拥有的引用,那么你需要做的主要有两点
- 释放CoreFoundation对象
- 解除监听行为
以弱引用避免保留环
以“自动释放池块”降低内存峰值
自动释放池还有变量可见范围的限制
1
2
3
4@autoreleasepool {
id object = [self createObject];
}
[self useObject:object]; // 报错,因为object变量已经不可见了
用“僵尸对象”调试内存管理问题
向已经回收的对象发送消息是非常不安全的。如果该内存已经被覆写了,那么程序就会崩溃;如果暂时没有被覆写,那么侥幸可以运行。所以这时候程序会偶尔报错,难以调试
这个时候就可以使用Cocoa提供的 僵尸对象 的调试方法
启用这一项调试功能之后:所有的本要被回收的对象会被转化成特殊的僵尸对象,这些内存不会被覆写;当僵尸对象收到消息后,他会将原本的对象信息打印出来,并提示说,你给一个已经回收的对象发送了信息
至于僵尸对象的工作原理,具体的看书~
不要使用retainCount
- ARC已经废弃
retainCount
方法
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.