ios消息转发机制

    Objective-C是使用传递消息的机制来调用函数,这就会使用到动态绑定的机制在运行期来决定到底调用哪个方法,甚至我们可以在运行时改变对象调用的方法。

    关于对象发送消息,首先在该类的struct objc_method_list列表中去搜索,如果找到则直接调用相关方法的实现,如果没有找到就会通过super_class指针沿着继承树向上去搜索,如果找到就跳转,如果到了继承树的根部(通常为NSObject)还没有找到。那就会调用NSObjec的一个方法doesNotRecognizeSelector:,这样就会报unrecognized selector 错误。其实在调用doesNotRecognizeSelector:方法之前还会进行消息转发---还有三次机会来补救。也就是常说的OC消息转发的三次补救措施。

总的来说一个OC消息的发送会经历四个阶段(该四个阶段都是搜索到NSObject再进入下阶段)

1.先在本类中搜索改方法的实现,如果有则直接调用若果没有则去父类中搜索直到NSObject,如果NSObject没有则进入消息转发(类的动态方法解析、备用接受者、完整的消息转发)。

2.类的动态方法解析:

    首先我们创建一个类ViewController;定义一个方法,但是不实现,这时候直接调用,程序会报错,直接crash,这时候如果我们实现了+ (BOOL)resolveInstanceMethod:(SEL)sel方法,并在里面实现动态方法的绑定,我们就可以正常的调用了,如图所示

1

可以看到虽然没有实现textAction:这个函数,但是我们通过class_addMethod动态添加dynamicMethodIMP函数,并执行dynamicMethodIMP这个函数的IMP。

3.消息的重新定位(备用接受者)

    当我们 没有 通过class_addMethod动态添加dynamicMethodIMP函数,并执行dynamicMethodIMP这个函数的IMP,就可以重新定位消息的接受者。如果目标对象实现了-forwardingTargetForSelector:,Runtime 这时就会调用这个方法,给你把这个消息转发给其他对象的机会。如图

2

这时候我们重新创建了一个text1_VC,并在.h里声明了textAction,在.m里实现了textAction方法。可以看到我们通过forwardingTargetForSelector把当前ViewController的方法转发给了text1_VC去执行了

4.完整的消息转发机制

如果在上一步还不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。首先它会发送-methodSignatureForSelector:消息获得函数的参数和返回值类型。如果-methodSignatureForSelector:返回nil,Runtime则会发出-doesNotRecognizeSelector:消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation:消息给目标对象。如图

3

从打印结果来看,我们实现了完整的转发。通过签名,Runtime生成了一个对象anInvocation,发送给了forwardInvocation,我们在forwardInvocation方法里面让text1_VC生成的对象去执行了textAction函数。

你可能感兴趣的:(ios消息转发机制)