您的位置:首页 > 移动开发 > IOS开发

iOS开发之Runtime运行时机制

2017-08-09 10:16 537 查看
摘要: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内存管理的引用计数机制。

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


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

NSObject+AssociatedObject.h

@interface NSObject (AssociatedObject)
@property (strong, nonatomic) id associatedObject;
@end


NSObject+AssociatedObject.m

@implementation NSObject (AssociatedObject)
- (void)setAssociatedObject:(id)associatedObject
{
objc_setAssociatedObject(self, @selector(associatedObject), associatedObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)associatedObject
{
return objc_getAssociatedObject(self, _cmd);
}
@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 级考试(答案和解释)

Objective C类方法load和initialize的区别

作者:Sam_Lau

链接:http://www.jianshu.com/p/25a319aee33d

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios