RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。runtime是一套比较底层的纯C语言API,属于1个C语言库,包含了很多底层的C语言API。 对于C语言,函数的调用在编译的时候会决定调用哪个函数(C语言的函数调用请看这里 )。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。
//www.greatytc.com/p/927c8384855a
如果用实例对象调用实例方法,会到实例的isa指针指向的对象(也就是类对象)操作。
如果调用的是类方法,就会到类对象的isa指针指向的对象(也就是元类对象)中操作。
(1)首先,在相应操作的对象中的缓存方法列表中找调用的方法,如果找到,转向相应实现并执行。
(2)如果没找到,在相应操作的对象中的方法列表中找调用的方法,如果找到,转向相应实现执行
(3)如果没找到,去父类指针所指向的对象中执行1,2.
(4)以此类推,如果一直到根类还没找到,转向拦截调用。
(5)如果没有重写拦截调用的方法,程序报错。
以上的过程给我带来的启发:
重写父类的方法,并没有覆盖掉父类的方法,只是在当前类对象中找到了这个方法后就不会再去父类中找了。
如果想调用已经重写过的方法的父类的实现,只需使用super这个编译器标识,它会在运行时跳过在当前的类对象中寻找方法的过程。
拦截调用
在方法调用中说到了,如果没有找到方法就会转向拦截调用。
那么什么是拦截调用呢。
拦截调用就是,在找不到调用的方法程序崩溃之前,你有机会通过重写NSObject的四个方法来处理。
+ (BOOL)resolveClassMethod:(SEL)sel;
+ (BOOL)resolveInstanceMethod:(SEL)sel;
//后两个方法需要转发到其他的类处理
- (id)forwardingTargetForSelector:(SEL)aSelector;
-(void)forwardInvocation:(NSInvocation *)anInvocation;
-
-第一个方法是当你调用一个不存在的类方法的时候,会调用这个方法,默认返回NO,你可以加上自己的处理然后返回YES。
-第二个方法和第一个方法相似,只不过处理的是实例方法。
-第三个方法是将你调用的不存在的方法重定向到一个其他声明了这个方法的类,只需要你返回一个有这个方法的target。
-第四个方法是将你调用的不存在的方法打包成NSInvocation传给你。做完你自己的处理后,调用invokeWithTarget:方法让某个target触发这个方法