第五章:内存管理
第二十九条:理解引用计数
理解引用计数这个可以通过《Objective-C 高级编程》这本书中的例子来理解,比较直观,大概如下:
alloc/new/copy/mutableCopy retain release dealloc等自动释放池: 可以看到在我们程序中入口文件main.m中main函数中就包裹了一层autoreleasepool
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([HSAppDelegate class]));
}
}
autoreleasepool可以延长对象的生命期,使其在跨越方法调用边界后依然可以存活一段时间,通常是在下一次“时间循环”(event loop)时释放,不过也可能会执行的早一点。
- 保留环: 也称retain cycle,就是循环引用。形成原因就是对象之间相互用强引用指向对方,会使得全部都无法得以释放。解决方案通常是使用弱引用(weak reference)
第三十条:以ARC简化引用计数
使用ARC,可以省略对于引用计数的操作,所以在ARC下调用对象的retain,release,autorelease,dealloc方法时系统会报错。
这里要注意CoreFoundation 对象不归ARC管理,开发中如果有用到还是要谁创建谁释放,适时调用CFRetain/CFRelease。
第三十一条:在delloc方法中只释放引用并解除监听
不要在delloc方法中调用其他方法,尤其是需要异步执行某些任务又要回调的方法,这样的很危险的行为,很可能异步执行完回调的时候该对象已经被销毁了,这样就没得玩了,crash了。
在delloc方法里应该制作一些释放相关的事情,包括不限于一些KVO取消订阅,remove 通知等。
第三十二条:编写“异常安全代码”时留意内存管理问题
这条有点重复,之前已经说过了,OC中抛出异常的时候可能会引起内存泄漏,注意一下使用的时机,或者注意在@try捕获异常中清理干净。
第三十三条:以弱引用避免保留环
这条比较简单,内容主旨就是标题:以弱引用避免保留环(Retain Cycle)
第三十四条:以“@autoreleasepool”降低内存峰值
在遍历处理一些大数组或者大字典的时候,可以使用自动释放池来降低内存峰值,例如:
NSArray *people = /*一个很大的数组*/
NSMutableArray *employeesArray = [NSMutableArray new];
for (NSStirng *name in people) {
@autoreleasepool {
MLEmployee *employee = [MLEmployee alloc] initWithName:name];
[employeesArray addObject:employee];
}
}
第三十五条:用“僵尸对象”调试内存管理问题
如上图,勾选这里可以开启僵尸对象设置。开启之后,系统在回收对象时,不将其真正的回收,而是把它的isa指针指向特殊的僵尸类,变成僵尸对象。僵尸类能够响应所有的选择子,响应方式为:打印一条包含消息内容以及其接收者的消息,然后终止应用程序
第三十六条:不要使用retainCount
在苹果引入ARC之后retainCount已经正式废弃,任何时候都不要调用这个retainCount方法来查看引用计数了,因为这个值实际上已经没有准确性了。但是在MRC下还是可以正常使用