深入理解Objective-C的Runtime机制


http://www.csdn.net/article/2015-07-06/2825133-objective-c-runtime/6



深入理解Objective-C的Runtime机制

发表于2015-07-06 11:53| 46846次阅读| 来源CSDN| 19 条评论| 作者刘耀柱

移动开发

Objective-C

开发经验

运行时

面向对象

机制

数据结构


摘要:Objective-C是基于C加入了面向对象特性和消息转发机制的动态语言,除编译器之外,还需用Runtime系统来动态创建类和对象,进行消息发送和转发。本文作者通过分析Apple开源的Runtime代码来深入理解OC的Runtime机制。


三种方法的选择

Runtime提供三种方式来将原来的方法实现代替掉,那该怎样选择它们呢?


  • Method Resolution:由于Method Resolution不能像消息转发那样可以交给其他对象来处理,所以只适用于在原来的类中代替掉。
  • Fast Forwarding:它可以将消息处理转发给其他对象,使用范围更广,不只是限于原来的对象。
  • Normal Forwarding:它跟Fast Forwarding一样可以消息转发,但它能通过NSInvocation对象获取更多消息发送的信息,例如:target、selector、arguments和返回值等信息。


Associated Objects

当使用Category对某个类进行扩展时,有时需要存储属性,Category是不支持的,这时需要使用Associated Objects来给已存在的类Category添加自定义的属性。Associated Objects提供三个API来向对象添加、获取和删除关联值:


  • void objc_setAssociatedObject (id object, const void *key, id value, objc_AssociationPolicy policy )
  • id objc_getAssociatedObject (id object, const void *key )
  • void objc_removeAssociatedObjects (id object )


其中objc_AssociationPolicy是个枚举类型,它可以指定Objc内存管理的引用计数机制。


[cpp] view plaincopy


  1. typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {  
  2.     OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */  
  3.     OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.  
  4.                                             *   The association is not made atomically. */  
  5.     OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied.  
  6.                                             *   The association is not made atomically. */  
  7.     OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object. 
  8.                                             *   The association is made atomically. */  
  9.     OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied. 
  10.                                             *   The association is made atomically. */  
  11. };  


下面有个关于NSObject+AssociatedObject Category添加属性associatedObject的示例代码:

NSObject+AssociatedObject.h


[cpp] view plaincopy


  1. @interface NSObject (AssociatedObject)  
  2. @property (strong, nonatomic) id associatedObject;  
  3. @end  


NSObject+AssociatedObject.m


[cpp] view plaincopy


  1. @implementation NSObject (AssociatedObject)  
  2. - (void)setAssociatedObject:(id)associatedObject  
  3. {  
  4.     objc_setAssociatedObject(self, @selector(associatedObject), associatedObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);  
  5. }  
  6. - (id)associatedObject  
  7. {  
  8.     return objc_getAssociatedObject(self, _cmd);  
  9. }  
  10. @end  


Associated Objects的key要求是唯一并且是常量,而SEL是满足这个要求的,所以上面的采用隐藏参数_cmd作为key。

Method Swizzling

Method Swizzling就是在运行时将一个方法的实现代替为另一个方法的实现。如果能够利用好这个技巧,可以写出简洁、有效且维护性更好的代码。可以参考两篇关于Method Swizzling技巧的文章:


  • nshipster Method Swizzling
  • Method Swizzling和AOP实践


Aspect-Oriented Programming(AOP)

类似记录日志、身份验证、缓存等事务非常琐碎,与业务逻辑无关,很多地方都有,又很难抽象出一个模块,这种程序设计问题,业界给它们起了一个名字叫横向关注点(Cross-cutting concern),AOP作用就是分离横向关注点(Cross-cutting concern)来提高模块复用性,它可以在既有的代码添加一些额外的行为(记录日志、身份验证、缓存)而无需修改代码。

危险性

Method Swizzling就像一把瑞士小刀,如果使用得当,它会有效地解决问题。但使用不当,将带来很多麻烦。在stackoverflow上有人已经提出这样一个问题:What are the Dangers of Method Swizzling in Objective C?,它的危险性主要体现以下几个方面:


  • Method swizzling is not atomic
  • Changes behavior of un-owned code
  • Possible naming conflicts
  • Swizzling changes the method's arguments
  • The order of swizzles matters
  • Difficult to understand (looks recursive)
  • Difficult to debug


总结

虽然在平时项目不是经常用到Objective-C的Runtime特性,但当你阅读一些iOS开源项目时,你就会发现很多时候都会用到。所以深入理解Objective-C的Runtime数据结构、消息转发机制有助于你更容易地阅读和学习开源项目。

扩展阅读


  • 玉令天下博客的Objective-C Runtime
  • 顾鹏博客的Objective-C Runtime
  • Associated Objects
  • Method Swizzling
  • Method Swizzling和AOP实践
  • Objective-C Runtime Reference 
  • What are the Dangers of Method Swizzling in Objective C?
  • iOS程序员6级考试(答案和解释)

作者简介:刘耀柱(@Sam_Lau_Dev),iOS Developer兼业余Designer,参与开发技术前线iOS项目翻译,个人博客:http://www.jianshu.com/users/256fb15baf75/latest_articles,GitHub:https://github.com/samlaudev


你可能感兴趣的:(iOS,Runtime)