Effective Objective-C 2.0 阅读笔记<三>

第五章 内存管理

1.ARC并不会调用retainrelease等方法,而是直接调用其底层C语言版本objc_retain等,所以ARC没有普通的OC消息派发机制。

2.如果setter方法像下面这样写,当新值和旧值相同时就程序就会崩溃。

-(void)setObject:(id)object{
[_object release];
_object=[object retain];
}

3.ARC中的命名规则:如果方法名以allocnewcopymutableCopy开头,则返回对象归调用者所有,否则返回的对象会自动释放。

4.dealloc方法里要释放指向其他对象的引用,取消键值观测(KVO)和NSNotificationCenter通知,不要在这里执行异步任务或应该在正常状态下执行的任务,因为这是的对象已经处于正在回收状态了。

5.ARC默认不生成安全处理异常的代码,设置-fobjc-arc-exceptions标志后可以开启,不过会导致应用程序变大,效率变低。

6.unsafe_unretainweak都可以用来消除循环引用,区别是前者在引用移除后仍然指向已经回收的对象,后者则会自动设为nil,所以使用weak会安全一点,因为向nil发送消息不会报错。

7.利用自动释放池可以避免内存峰值的出现。

第六章 块与大中枢派发

1.下图是块的内部结构:
image
上图中首个变量是个isa指针,所以块本身是一个对象。那么块和普通函数有什么区别呢?除了块是个对象外,其实最大的区别就是块比函数多了个上下文环境,块内部可以调用外部的变量,对应上图的variables,而descriptor内部则会对捕获的变量进行管理。

2.块分为全局块(NSConcreteGlobalBlock)、栈块(NSConcreteStackBlock)、堆块(NSConcreteMallocBlock),在ARC中只有全局块和堆块了。

3.利用typedef创建块,然后将handler块作为参数传给方法,以降低代码分散程度。这种方法编写类的时候特别要注意块的保留环,记得要把块在适当时机释放掉,解除保留环。在AFNetworking中,是把所有competition块保存在字典中,当请求结束时,再移除,其他开源库的做法也都大同小异。

4.GCD和NSOperationQueue:前者是纯C的API,且更加轻量,后者是Objective-C对象,可以取消操作、设置依赖关系、同一队列中各操作的优先级设置。

5.不要使用dispatch_get_current_queue,因为往往A线程里面又有B线程,所以在B中检测当前线程就会产生歧义。

第七章 系统框架

1.多用块枚举,少用for循环,另外也可以使用for in这种快速遍历的方法。

2.loadinitialize里面的代码一定要精简。不要在里面调用其他类的方法,因为多个类之间执行load的顺序是不确定的,而且load不参与继承机制。initialize会在类被第一次调用时执行一次,和load一样,不要再里面调用其他类的方法。

3.NSTimer会保留目标对象,所以很容易造成循环引用,调用invalidate方法可以使timer失效,但是别把这项工作交给调用者,你永远无法保证调用者一定会调用invalidate

结语

这本书其实早就看完了,写这几篇博客时,这本书差不多看了快三遍了,里面很多知识点对提升编程质量还是很有帮助的,在看一些开源iOS框架的时候,很多细节上的处理都能在这本书上找到解释。