iOS中runtime的一些使用总结

我们都知道OC是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。对于OC来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。Runtime基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。这里对于runtime的原理不再赘述,我们来谈谈一些具体应用。

目前使用比较多的对于runtime的应用如下:

1,使用method_swizzling对一些已知方法进行替换,特别是系统框架的一些方法,达到一些全局修改方法表现的目的。

2,通过对消息转发中一些异常处理方法的实现,防止应用crash。

3,通过关联对象动态的给对象增加属性。

4,KVO的实现。

下面来简单的说一下这些应用的实现原理和使用。

1,我们通常在一个类的load方法中,使用method_swizzling对类中要替换的方法进行替换。对于不开源的系统方法,可以在分类中的load方法中进行替换。能够进行替换的支持来自于runtime。由于runtime中使用msg_send(obj,CMD)的方式进行消息分发,我们在调用[object message]时,实际上会转换成msg_send(object,message)的c方法进行调用,而这个c方法会在object的结构体中,通过message即CMD,在方法表中查找匹配的CMD,找到则调用对应的方法,找不到则去父类中寻找。method_swizzling即是修改了一个类对象中的方法列表里的方法指针和指向的方法的具体实现,简单来说,就是CMD_A本来指向IMP_A,所以我们对一个对象发送CMD_A调用的应该是IMP_A方法,而经过method_swizzling后我们让CMD_A指向了IMP_B,这时我们在调用对象的CMD_A方法时,实际上调用的就是IMP_B了。method_swizzling给了我们一种能力,可以在不修改源文件,或者不知道源文件实现的情况下,在运行时动态的改变一个方法的表现。具体实现代码不表。

2,消息转发。在msg_send(object, CMD)之后,很有可能这个CMD方法根本不存在,这时候就会触发runtime的消息转发。会经历三个阶段:

动态消息转发:

+resolveInstanceMethod:(实例方法)或者

+resolveClassMethod:(类方法)。

备用接收者:

- (id)forwardingTargetForSelector:(SEL)aSelector

完整的消息转发:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

- (void)forwardInvovation:(NSInvocation)anInvocation

当前类对象中找不到对应的消息时, 会通过isa指针找到父类,在父类的方法表中查找方法,直到找到NSObject根类为止,如果还没有找到对应的方法,就会触发消息转发。首先通过resolveInstanceMethod可以动态添加方法,如果返回了方法,则调用动态添加的方法。如果动态消息转发的方法没有实现,会调用forwardingTargetForSelector:(SEL)aSelector ,这里可以返回一个备用的消息接受者对象,这里如果返回了消息接受者对象,则消息转发给了备用接收者,当前转发流程终止(这也是实现仿多继承的机制,可以在当前类声明一些空方法,在另一个类中实现,将这个类作为当前类对象的备用接收者)。如果没有返回备用备用接收者,则进入最后完整的消息转发。我们经常见到的unrecgnized Selector send to obj就是这这一步抛出的异常,在这里可以拦截,做一些自己想做的事,防止应用崩溃。

3,关联对象。通过objc_setAssociatedObject 和objc_getAssociatedObject,可以像使用字典一样为当前类添加关联对象,从而为向前对象动态添加了属性。这种比较适合给系统框架添加属性的情况。

4,KVO的实现。我们在使用addobserverForKey:添加对某个属性的监听的时候,实际上runtime动态生成了一个新的类对象,这个新的类继承自被监听属性所在的类,并重写了被监听属性的set方法,从而在属性改动的时候,触发回调通知监听者属性被修改了。这里用到了很重要的isa指针,当前对象的isa指针在被添加监听之后,指向的就不是当前的类对象了,而是新生成的重写了set方法的类对象。

目前runtime使用比较多的是这样的一些场景。runtime在一些时候可以很方便的修改一些表现,比如全局修改app的字体。但是这样会在维护的时候引发一些问题,特别是在团队内使用的时候,应该注意影响面。


Powered By Z-BlogPHP 1.7.3

Copyright 粤ICP备2024347557号 Rights Reserved.