ios&&OC

Objective-C 的消息转发

2019-08-14  本文已影响0人  kindom_0129

消息在OC中方法调用是一个消息发送的过程。OC方法最终被生成为C函数,并带有一些额外的参数(self 、_cmd)

objc_msgSend(void /* id self, SEL op, ... */ )

OC的方法本质


[array insertObject:obj atIndex:5];
//等价于
objc_msgSend(array, @selector(insertObject:atIndex:), obj, 5);

OC消息转发的步骤


1.通过 \color{red}{recevier }\color{red}{isa}指针 找到 \color{red}{recevier}\color{red}{Class(类)}
2.在 \color{red}{Class(类)}\color{red}{cache}(方法缓存) 的散列表中寻找对应的\color{red}{IMP}(方法实现);
3.如果在\color{red}{cache}(方法缓存) 中没有找到对应的 \color{red}{IMP}(方法实现) 的话,就继续在\color{red}{Class(类)}\color{red}{method list}(方法列表) 中找对应的 \color{red}{selector},如果找到,填充到 \color{red}{cache}(方法缓存) 中,并返回 \color{red}{selector}
4.如果在\color{red}{Class(类)} 中没有找到这个 \color{red}{selector},就继续在它的 \color{red}{superClass}(父类)中寻找;
5.一旦找到对应的 \color{red}{selector},直接执行 \color{red}{recever}对应 \color{red}{selector} 方法实现的 \color{red}{IMP}(方法实现)。
6.若找不到对应的 \color{red}{selector},要开始进入 \color{red}{动态方法解析和消息转发},消息被转发或者临时向 \color{red}{recever} 添加这个 \color{red}{selector} 对应的实现方法,否则就会发生崩溃。

+ (BOOL)resolveInstanceMethod:(SEL)sel;
+ (BOOL)resolveClassMethod:(SEL)sel;

- (id)forwardingTargetForSelector:(SEL)aSelector;

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)anInvocation;

OC 中给一个对象发送消息的完整步骤:


1.在对象类的 dispatch_table 中尝试找到该消息。如果找到了,跳到相应的函数IMP去执行实现代码(参考OC消息转发的步骤);
2.如果没有找到,运行时系统会发送+resolveInstanceMethod:或者 +resolveClassMethod:尝试去 resolve 这个消息;
3.如果 resolve 方法返回NO,运行时系统就发送 -forwardingTargetForSelector: 允许你把这个消息转发给另一个对象;(resolve 方法返回YES时,运行时系统就会重新启动一次消息发送的过程)
4.如果没有新的目标对象返回,运行时系统就会调用 -methodSignatureForSelector:和-forwardInvocation: 消息。你可以发送-invokeWithTarget:消息来手动转发消息或者发送 -doesNotRecognizeSelector:抛出异常;
5.如果都没有,系统抛出异常。

类方法的调用过程 和对象方法调用差不多,流程如下:


1.通过类对象\color{red}{isa}指针 找到所属的\color{red}{Meta Class} (元类);
2.在 \color{red}{Meta Class} (元类) 的\color{red}{method list}(方法列表) 中找到对应的 \color{red}{selector};
执行对应的 \color{red}{selector}

注意
需要注意的是类方法的解析,动态增加方法时候,需要加到元类上,因为类方法列表是在元类对象中存储的。

上一篇下一篇

猜你喜欢

热点阅读