runtime总结之消息机制的方法转发,方法交换

runtime总结之消息机制的方法转发,方法交换



runtime的消息机制

总结:

发送一个消息:底部会转成objc_msgSend函数,这个函数除了方法的参数之外还有两个隐藏的参数self和_cmd,接下来就会按照下面的流程去调用这个函数

1.根据isa指针找到对象所属的类或者类所属的元类

2.先去类或者元类的cache列表中根据SEL去找这个方法。

3.没有找到,去method方法列表中找

4.还是没有找到,就去父类中找

5.找到了,根据SEL找到对应的IMP,调用这个函数

6.没有找到,进入动态方法解析或者消息转发。

动态方法解析:

runtime提供的第一次实现这个方法的机会,要实现resolveInstanceMethod/resolveClassMethod方法,给未实现的方法在运行时添加实现,返回no/不实现,进入消息转发。

消息转发一:消息重定向

消息重定向:返回一个实现了该方法的对象,要实现-(id)forwardingTargetForSelector:(SEL)aSelector函数,如果返会nil/self,则进入下面的消息转发二

消息转发二:消息转发

将未实现方法的相关信息打包成一个NSInvocation对象,然后交给一个类去实现。需要实现-(NSMethodSignature )methodSignatureForSelector:(SEL)aSelector和-(void)forwardInvocation:(NSInvocation )anInvocation方法

疑问?为什不直接找IMP而要通过SEL这个中间人呢?

SEL只是方法的编号,真是的实现是通过IMP来查找的,SEL和IMP之间是一一映射的关系,通过SEL我们可以改变他的IMP,然后让一个方法在不同的情况下有不同的实现,例如实现方法的交换,有时候我们需要给系统的方法添加一些自己的东西 

1:可以通过一个子类继承于系统类,然后重写那个类的方法 

2:通过分类,但是会覆盖系统的方法 

3:写一个自己的方法,通过runtime在load方法中交换系统方法和自己的方法的实现 

下面主要针对第三种例子举例: 

第一步首先为我们要动手脚的系统方法类添加一个分类, 

假设我们要为imageNamed添加一个判断nil的功能,先要为他添加一个分类,然后给系统的imageNamed方法添加前缀,明明一个自己的方法,如下 :


分类的h文件 

runtime总结之消息机制的方法转发,方法交换_第1张图片

分类的m文件,对于这里乍一看可能像递归,其实在第一次调用的系统的imageNamed方法时调用的是my_imageNamed方法,当第调用的my_imageNamed方法时其实在调用系统的imageNamed方法 

runtime总结之消息机制的方法转发,方法交换_第2张图片

交换 

runtime总结之消息机制的方法转发,方法交换_第3张图片

借鉴原文地址:https://blog.csdn.net/li15809284891/article/details/54767504?utm_source=copy

你可能感兴趣的:(runtime总结之消息机制的方法转发,方法交换)