读“编写高质量iOS与OSX代码的52个有效方法”笔记(03)

内存管理

第29条:理解引用计数

Objective-C 语言使用引用计数器来管理内存,每个对象都有个可以递增或递减的计数器。对象创建好之后,其保留计数至少为1,若保留计数为正,则对象继续存活,当保留计数降为0时,对象被销毁。
在对象的生命周期中,其余对象通过引用来保留或释放此对象。保留或释放操作分别会递增或递减保留计数。

注意retain,release,autorelease,这三个方法操作计数器。

第30条:以ARC简化引用计数

ARC,即自动管理计数器。
在ARC中,变量的内存管理语义可以通过修饰符指明,而原来则需手工执行”保留“及释放操作;(__strong,__weak,一个保留值,一个不保留值)。
注意的是ARC只负责管理Objective-C对象的内存。注意:CoreFoundation对象不归ARC管理,必须适时调用CFRetain/CFRelease

第31条:在dealloc中只释放引用并解除监听
- (void)dealloc
{
//    CFRelease(COREFOUNDATIONObject);
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
第32条:编写”异常安全代码“时留意内存管理问题
@try {
  // 可能会出现崩溃的代码
}
@catch (NSException *exception) {
    // 捕获到的异常exception
}
@finally {
    // 结果处理,也可以去掉
}

简单的来说,Apple虽然同时提供了错误处理NSError)和异常处理(exception)两种机制,但是Apple更加提倡开发者使用NSError来处理程序运行中可恢复的错误。而异常被推荐用来处理不可恢复的错误。

第33条:以弱引用避免保留环

保留环也就是我们常说的循环引用。就是有时候我们需要将某些引用设为weak,可避免出现“保留环”。

第34条:以”自动释放池块“降低内存峰值

自动释放池用于存放那些需要在稍后某个时刻释放的对象。

NSArray * dataRecord = /*****/;
NSMutableArray * testPeopleArray = [NSMutableArray array];
for(NSDictionary * recordDic in dataRecord)
{
    TestPeople * people = [[TestPeople alloc] initWithRecord:recordDic];
    [testPeopleArray addObject:people];
}

当循环长度无法预估,需要读出很多对象的时候,像上面中,会有一些临时对象产生,内存中会有很多不必要的临时对象,他们本该提早回收的,增加一个释放池就好啦。

NSArray * dataRecord = /*****/;
NSMutableArray * testPeopleArray = [NSMutableArray array];
for(NSDictionary * recordDic in dataRecord)
{
    @autoreleasepool {
        TestPeople * people = [[TestPeople alloc] initWithRecord:recordDic];
        [testPeopleArray addObject:people];
    }
}

注意不要把for循环放到释放池里面,特别是循环长度特别长的时候。

第35条:用”僵尸对象“调试内存管理问题
读“编写高质量iOS与OSX代码的52个有效方法”笔记(03)_第1张图片
Xcode中的Scheme编辑器

启动这项调试功能之后,运行期系统会把所有已经回收的实例转化成特殊的“僵尸对象”,而不会真正的回收他们。这种对象所在的核心内存无法重用,因此不可能遭到覆写。僵尸对象收到消息后,会抛出异常,其中准确说明了发送过来的消息,并描述了回收之前的对象。

第36条:不要使用retainCount

对象的保留计数看似有用,实则不然,因为任何给定时间点上的“绝对保留技术”都无法反映对象的生命期的全貌。

但是这个其实我们一般也不会用,ARC环境下已经禁止啦。

持续记录中····

你可能感兴趣的:(读“编写高质量iOS与OSX代码的52个有效方法”笔记(03))