《Objective-C 高级编程 iOS与OS X多线程和内存管理》 核心札记一

来源:互联网 发布:java实现短信发送功能 编辑:程序博客网 时间:2024/05/01 12:31

苹果源代码不会告诉你的

——引子

近日偶借一本图灵出版的程序书籍,是由日本资深软件工程师 K.S. (Twitter:@splhack) 和 TF (Twitter:@munakoiso) 合作编写,国内 黎华 译,全书共三章,分别是 ARC,Blocks 和 Grand Central Dispatch,简称GCD ,共186 页,本以为又是抄袭官方SDK的一本入门级书籍,想随便翻翻,于是直到清明第一天才翻阅,可是,这完全颠覆了之前所有的相关书籍,之前的iOS教程基本都是教你如何用,怎么使用这些SDK,而这本书却是告诉你为什么要这么用,比如ARC底层是如何实现的,涉及C,指针等底层代码,预测苹果官方底层代码,通过实例验证预测,知道苹果的源代码到底做了什么,不过,这本书不推荐刚入门的朋友阅读,适合半年开发以上的朋友进一步了解新特性底层如何实现。


核心札记一  ARC篇章    阅读地点:北京 肯德基店  2014.4.6

1,内存管理的实质就是引用计数机制,作者用了进出办公室开灯,关灯的实例来说明,很形象,不必多言;


2,ARC 作者讲到内存的管理是由 编译器 来管理,这个后面作者做了验证,并不认可全部内存都是由编译器来管理(官方解释ARC),通过代码预测得有时候还是需要OC 运行时库的协助,即ARC下需要以下工具和库来实现:a) clang (LLVM编译器)3.0以上,b) objc4 OC 运行时库493.9以上;


3,作者这里对比的底层源码来自 GNUstep,借助它来分析苹果的底层源代码,批注:GNUstep(http://gnustep.org)和苹果的Cocoa(http://opensource.apple.com) 两者的行为和实现方式站在使用者的角度来说非常相似,理解了GNUstep就等于理解了苹果的Cocoa实现;


专栏

NSZone是防止内存碎片化引入的结构,多重区域分割了内存,主要目的是防止内存碎片化,但是苹果官方文档解释目前的运行时系统简单的忽略了区域的概念,运行时系统中的内存管理本身已经极具效率,故而不在用区域来管理内存。


4,推测苹果是通过散列表管理引用计数,GNU是把引用计数保留在头部的内存变量中,看了起来比较高效,但是苹果的好处为无需考虑内存块头部,可以通过记录表追溯到各对象的内存块,而且如果用工具检测内存泄露时,引用计数的各记录也有助于检测各对象的持有者是否存在;


5,作者把局部变量翻译成自动变量,有点绕,在对象放入pool后,当pool被drain时候,就对里面的各个对象发送release,注意,作者讲到NSRunLoop 每次循环过程中 NSAutoreleasePool对象被生成或废弃,故而不要滥用自动释放,这里也举例说明一个大量的循环里面必须使用自动释放池及时释放每次循环生成的对象,面试题中常见,通过对源代码的分析,作者得出 autorelease 实例方法的本质就是调用NSAutoreleasePool对象的addObject 类方法;


专栏

提高调用Objective-C方法的速度,在GNU里面的autorelease 是用一种特殊的方法实现的,被称为 IMP Caching,即在框架初始化时对其结果值进行缓存,方法调用就是使用缓存的结果值,这里有点模糊;


专栏

如果对pool对象发送 autorelease 将会发生异常,在OC中对一个对象发送autorelease,都是调用NSObject类的autorelease,但是对NSAutoreleasePool类,autorelease实例方法已经被该类重载,因此运行时就要出错,错误:cannot autorelese an atuorelese pool ;


6,ARC的使用从本质上说并没有改变“引用计数式内存管理”,可以指定编译器为:-fobjc-arc,ARC下的修饰符:__strong,__weak,__unsafe_unretained,__atuoreleasing,a)__strong修饰符是默认,如 id obj ==id __strong obj,即强引用,b)__weak,弱引用, 主要是为解决 ”循环引用“ 而使用,引用计数式必然会引起循环引用,这是不可避免的,常见为对象之间互相强引用,还有就是对自身的强引用,主要不能这样 id __weak obj =[ [NSObject alloc] init],可以使用 id __weak obj1 = obj,c)__unsafe_unretained是不安全的所有权修饰符,它修饰的变量不属于编译器的内存管理,注意,ARC式的内存管理是编译器的工作,d) ,__atuoreleasing 该修饰符下的变量等价于MRC下调用对象的autorelease方法,可以理解为在ARC下用@autoreleasepool替代NSAutoreleasePool类,用附有__atuoreleasing修饰符的变量替代autorelease方法,但是基本不常见这种修饰符;


7,在LLVM3.0以上,MRC和ARC下都可以使用@autorelease块,因为autoreleasepool范围以块级源代码表示,提高了程序的可读性,NSRunLoop均能随时释放注册到autoreleasepool中的对象。


专栏

__strong 类似于C++ 中的 std::shared_ptr ,__weak 类似于C++的std::shared_ptr;

ARC下注意不能使用区域(NSZone),不要显示调用dealloc;


8,通过__bridge可以将 id 和 void * 之间相互转换,__bridge 转换中还有两种是__bridge_retained 和 __bridge_transfer,类似strong和weak;


9,CF 和 F框架下的转换通常就是用的Toll-Free-Bridge,即免费桥;


10,不支持__weak 修饰符的类,其类声明中附加了__attribute__ 这一属性,在cocoa框架类中不支持__weak的极为罕见,还有一种情况下也不能使用__weak修饰符:-(BOOL)allowsWeakReference;返回为NO时,-(BOOL)retainWeakReference 返回为NO时;


11,讲对象赋值给附有__autoreleasing修饰符的变量等同于MRC时调用对象的autorelease方法;


总结:这一篇章主要讲述通过对比GNU来推测苹果官方代码,对底层的代码分析来论述ARC和MRC的区别和为什么使用这些修饰符,以及它们的好处,读完,对这些新特性理解更加到位,的确受益匪浅。





1 0
原创粉丝点击