iOS runtime 机制

OC 当中,runtime 可以说是重中之重,很多的第三方SDK,诸如: Aspects、JSPatch等,都是利用runtime 实现的。

那么runtime究竟是什么呢? 

一、运行时语言

OC作为运行时语言,和其他语言在编译期就已经确定了方法的具体执行内容不同,OC是在运行期去判断执行内容。

runtime 就是在运行期查找调用方法的过程, 即 [object msgSend].

二、类与对象

作为面向对象的语言,万物皆为对象,而对象是由 类 实例化而来。

在OC当中,类的结构为:

struct objc_class {

    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__

    Class _Nullable super_class                     OBJC2_UNAVAILABLE;

    const char * _Nonnull name                              OBJC2_UNAVAILABLE;

    long version                                            OBJC2_UNAVAILABLE;

    long info                                                OBJC2_UNAVAILABLE;

    long instance_size                                      OBJC2_UNAVAILABLE;

    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;

    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;

    struct objc_cache * _Nonnull cache                      OBJC2_UNAVAILABLE;

    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;

#endif

} OBJC2_UNAVAILABLE;

其中isa 指向Class 的 元类(meta-class), super_class 指向Class的父类。

其继承链为: 


iOS runtime 机制_第1张图片
OC 继承


meta-class的isa 指针最终指向 NSObject 的meta-class.

NSObject的meta-class的isa 指针 指向自身,super_class指向NSObject.

什么是meta-class?

在结构体当中,声明了isa变量,指向meta-class.

Class _Nonnull isa OBJC_ISA_AVAILABILITY;

一个类,可以有实例方法,也可以有类方法。所有的实例方法都存储在类的 methodLists:

struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;

而类方法就存储在了meta-class的methodLists当中。

当调用类方法时,会在类的isa指针所指向的meta-class的方法列表当中查找。

那么meta-class的isa指针指向哪里呢? OC的设计者让所有的meta-class的isa指针都指向了NSObject的meta-class;

也就是说: 任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己的所属类,而基类的meta-class的isa指针是指向它自己。

三、消息传递机制

作为运行时语言,OC在运行时才会查找方法的具体实现,即:

objc_msgSend(receiver, selector, arg1, arg2,...)

通过这个方法来查找方法对应的实现。

1. 首先判断 Obj 实例是否为nil,若为nil 则不作任何操作返回nil;

2.若obj不为空,如果是实例方法,则在obj的cache 中查找是否存在 相应的SEL

3. 如果cache中没有,则继续在 methodLists 当中查找

4. 如果还是没有找到相应的SEL,则沿着 obj的superClass逐级查找,直至NSObject类

5. 如果在继承链中没有找到SEL,则执行消息转发机制。

如果找到了SEL方法,则根据SEL查找Method,找到对应的实现方法IMP。

四、消息转发机制

没有找到相应的实现方法时,OC就会执行消息转发,给以三次的机会来避免程序crash。


iOS runtime 机制_第2张图片
消息转发机制


如上图所示,消息转发机制分为三个步骤

1、动态方法解析

+resolveInstanceMethod: // 对应实例方法

+resolveClassMethod: // 对应类方法

可以通过 class_addMethod()方法,动态为SEL添加实现方法,同时返回true,

2、备用接收者

- (id)forwardingTargetForSelector:(SEL)aSelector

这步可以指定某个对象作为接收者来相应消息,如果返回nil,则进入第三步;若返回不为空的对象,则将在其方法列表中查找合适的SEL 执行。

3、完整消息转发

如果前两步都没有做任何操作,系统将会把未实现的SEL及对应的class 分装成NSInvocation对象抛出。

- (void)forwardInvovation:(NSInvocation)anInvocation

可以在此步中实现方法,修改相应对象等,如果调用成功,则结束;如果没能正确相应方法,则会抛出异常,程序crash。


参考:

https://www.tuicool.com/articles/Av63EfJ

https://www.jianshu.com/p/58c985408b75

http://blog.devtang.com/2013/10/15/objective-c-object-model/

你可能感兴趣的:(iOS runtime 机制)