首先要知道咱们写的代码在程序运行过程当中都会被转化成runtime的C代码执行。缓存
runtime突出的一点就是OC中消息传递机制的应用。objc_msgsend(target,SEL);设计
首先咱们先看一下runtime的定义文件指针
OC中的一切都被设计为了对象,这些对象在Runtime中用struct(结构体)来表示。对象
下面来看一下runtime的经常使用功能获取类的系列列表blog
定义以下一个类:get
方法调用在runtime(运行时)的调用过程,例如【self way】在runtime中会被转化为 objc_msgSend(self, @selector( way )).it
若是用实例对象调用实例方法,那么系统回到实例对象的 isa 指针指向的对象中找到该方法进行操做。io
若是用类调用类方法,那么系统回到类对象的 isa 指针指向的对象中操做。变量
在对象中找方法的时候,首先要在isa指针指向的对象中的缓存方法列表中找该方法,若是找到直接拿来用,反之若是没有找到,那么接着会到该对象的方法列表中找,若是找到直接拿来用,若是没有找到,那么就去对象的父类的isa指针中指向的对象中找,找的过程仍是跟上面同样,先从缓存中找。若是一直都没有找到该方法,那么就要转到拦截调用方法了(NSobjct对象中的方法),若是没有实现拦截方法,那么程序就会报错。打包
总结出来就是,当调用方法的时候,会进行如下操做:
一、 从自己的isa指针所指对象的缓存方法中找,若是找到直接转向相应的方法实现,若是没有找到转向2
二、从对象的方法列表中找,若是找到直接用,若是没有找到转向3
三、从对象的父类的isa指针所指的对象的缓存方法中找,若是找到直接转向方法的实现,没有的话转向4
四、从父类isa指针所指对象的方法列表中找,若是找到直接转向方法的实现,没有的话转向5
五、到超父类尚未找到的话,就须要转到拦截调用啦。
六、若是拦截调用方法没用实现的话程序就要报错了。
拦截调用就是当没有找到调用的方法的时候会转向拦截调用(NSObjec对象中的方法)
拦截调用通常都是经过下面四个方法来实现的
- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
这个方法是把你调用的不存在的方法重定向到一个其余声明了这个方法的泪,只须要你返回一个有这个方法的target
这个方法是把你调用的不存在的方法打包成NSInvocation传给你,作完本身的处理后调用 invokeWithTarget:方法让某个targer触发这个方法。
这个方法是当你调用一个不存在的类方法的时候,会调用这个方法,能够在这里加上本身的处理而后返回YES,这里默认是返回NO的;
+ (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);
这个方法是当你调用一个不存在的实例方法的时候触发的;
当调用一个不存在的方法的时候,被拦截到后,若是不处理,仍然是没有改方法的,程序仍然会出错。
有一个方法是根据传进来的SEL的类型来动态的添加方法的。
4个参数分别表示
Class cls 给哪一个类添加方法
SEL name 添加的方法
IMP imp 方法的实现,C方法的实现能够直接获取,OC的方法实现须要调用+(IMP)instanceMethodForSelector:(SEL)aSelector 来调用方法
“v@:*”方法的签名,表明有一个参数的方法