iOS 消息机制详解
应用
解决NSTimer、CADisplayLink循环引用。
二者都是基于runloop的定时器,由于处理事件内容不一样,runloop 每运行一次运行耗时就不一样,无法准确的定时触发timer的事件。
NSProxy 与 NSObject
如果继承自NSProxy
直接开始消息转发,NSProxy 是没有父类的。
继承NSProxy的类,调用isKindOfClass,会返回true,消息转发会用 target 本身做判断
如果继承自NSObject
isa 查找
isa 在当前类的方法缓存、方法列表中,找不到方法实现时,如果存在继承,会借助superclass寻找父类的方法缓存、方法列表中,找方法实现。
动态解析阶段
本质是调用了 objc_msgSend()
如果 isa 找到最后,找到原类还是找不到方法实现,就进入动态解析阶段。
此时,系统会再次通过 isa ,从类对象或者原类对象依次查找以下两个方法的实现:
+ (BOOL)resolveInstanceMethod:(SEL)sel // 对应实例方法
+ (BOOL)resolveClassMethod:(SEL)sel // 对应类方法
对应 runtime 源码:
举例:
消息转发阶段
继承自 NSObject 的情况下,如果动态解析阶段依然找不到方法实现,则进入消息转发阶段。
将消息转发给能处理消息的对象或者类:
- 类方法
+ (id)forwardingTargetForSelector:(SEL)aSelector
+ (void)forwardInvocation:(NSInvocation *)anInvocation
- 对象方法
- (id)forwardingTargetForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation