Runtime中具体的方法调用流程

  1. 首先,在相应操作的对象中的缓存方法列表中找调用的方法,如果找到,转向相应的实现并执行;
  2. 如果没找到,在相应操作的对象中的方法列表中找调用的方法,如果找到,转向相应的实现并执行;
  3. 如果没找到,去父类指针所指向的对象中执行1、2;
  4. 以此类推,如果一直到根类都没有找到,转向拦截调用,走消息转发机制
  5. 如果没有重写拦截调用方法,程序报错;

拦截调用

在方法调用中说到了,如果没有找到方法就会转向拦截调用。
那么什么是拦截调用呢?
拦截调用就是,在找不到调用的方法程序崩溃之前,你有机会通过重写NSObject的四个方法来处理:

+ (BOOL)resolveClassMethod:(SEL)sel;
+ (BOOL)resolveInstanceMethod:(SEL)sel;
//后两个方法需要转发到其他的类处理
- (id)forwardingTargetForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)anInvocation;

拦截调用的整个流程即Objective-C的消息转发机制。其具体流程如下图:
流程图

[image:A6043816-2585-4477-BE08-5C38F761E7E6-417-00001981CC42BFC1/message_forwarding.png]
由上图可见,在一个函数找不到时,runtime提供了三种方式去补救:

  1. 调用resolveClassMethod:(SEL)sel给个机会让类添加这个实现这个函数
  2. 调用forwardingTargetForSelector:(SEL)aSelector让别的对象去执行这个函数
  3. 调用forwardInvocation:(NSInvocation *)anInvocation(函数执行器)灵活的将目标函数以其它形式执行

如果都不中,调用doesNotRecognizeSelector抛出异常

本文固定链接: http://www.js-code.com/ios/ios_52585.html