Runtime探索

96 阅读2分钟

RunTime探索

1、Runtime是什么? Runtime是OC基于C、C++封装的运行时API。

2、方法的本质是什么? Runtime底层在OC方法进行调用时,底层会编译为objc_msgSend进行调用,如下图所示

(Clang编译完毕后的方法调用) (OC原方法)

由此我们可以看出,方法的底层调用为消息发送。

3、类的本质是什么? 同理通过上面的方法可以看出类在底层为 typedef struct objc_object User (objc_objcet源码)

4、runtime如何通过方法名称查找到方法的? 方法分为两类(对象方法和类方法)

对象方法调用(获取当前类的实例)
((void (*)(id, SEL))(void *)objc_msgSend)((id)user, sel_registerName("run"));
类方法调用 (获取当前类)
((void (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("User"), sel_registerName("walk")); 

找到对应的方法我们需要了解的是方法的存储,对象方法和类方法的存储是不一样的,对象方法存储在类中,类方法的存储是在元类中,元类对象的方法存在根元类中。对象本身是一个带isa指针的结构体,所以在像一个对象发送消息的时候,实际上是通过isa在对象的类别中找到对应的方法。下附isa走位流程图 由图可简易得知方法的查找顺序: 1、方法会在缓存表中进行查找是否有SEL对应的IMP,如果的查找到,直接通过函数指针IMP找到方法的具体实现,执行方法。 2、如果方法没有存在缓存表中,就会根据类对象的方法列表进行对应的匹配查找,如果查找成功,,如果没有找到,就会根据类对象的superclass指针查找父类,(重复上述1,2流程),直到找到NSObject。 3、如果依旧没有找到对应的方法实现,就会进行方法决议(method resolve)。首先判断object的类对象是否实现了resoloveinstaceMethod:放法,如果实现了,会进行调用,这时候我们可以动态添加SEL,之后会重新进行查找方法流程,如果没有实现该方法,就行进行消息转发。 消息转发如上图所示。 1、调用函数forwardingTargetForSelector,尝试找到一个能响应该消息的对象,如果找到转发给他,如果没有找到,进行下一步 2、调用methodSignaturForSelector,获取一个方法签名,如果获取不到,则直接调用doesNotRecognizeSelecton抛出异常。 3、调用forwardinvocation方法将第2获取到的方法签名包装为invocaiotn传入,进行自定义处理。

5、runtime的作用

通常我们使用runtime进行的操作有,方法的交换,方法异常的处理,关联对象,数据解析,动态页面等。