OC Runtime小记 (三) 消息转发

OC Runtime小记 (三) 消息转发

OC消息的传递方式

前两篇已经讲过,OC调用方法会触发objc_Send函数,具体消息函数的执行步骤如下

  • 1 通过isa指针找到objc_class
  • 2 查找类的objc_cache 查勘缓存内有没有方法
  • 3 查找类的方法列表objc_methodList
  • 4 如果找到了名称相符的SEL,则跳转至其实现
  • 5 如果为找到则在该类的父类中找,
  • 6 如还为找到,则转发消息,
  • 7 全部走完还为找到的话则报:unrecognized sector错误

其实可以理解OC方法是一个带有self 和 _cmd 的方法

void ocMethod(id self, SEL _cmd) {
    // implementation ....
}

程序在crash之前会执行这几个函数即消息转发

  • 1 动态方法解析

在对象接收到未知消息时,首先会调用该类 resoveInstanceMethod 方法,或者 resovleClass method 方法,在该方法中我们对这个未知消息添加一个处理方法,不过要先在该类中有实现该方法,可以用 class_addMethod 方法动态添加消息。

+ resolveInstanceMethod:(SEL)sel // 对应实例方法
+ resolveClassMethod:(SEL)sel // 对应类方法
  • 2 备用接受者

如果对象实现了以下方法,并为返回nil,那么返回的对象会作为新的消息新的接收者,会由返回的对象处理这个消息,这个对象不能为self,不然会无限循环。如果这个类中木有aSelector返回结果,那么应该调用父类返回结果。

- (id)forwardingTargetForSelector:(SEL)aSelector
  • 3 完整消息转发

若果以上方法还未能处理未知消息,接下来就需要做完整的消息转发了,完整的消息转发会调用2个方法:

-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector

- (void)forwardInvocation:(NSInvocation *)anInvocation

首先需要产生方法签名NSMethodSignature 要确保 NSInvocation 转发的类可以执行。