本篇是「消息转发」系列的第三篇, 在 OC-RunTime: 消息转发之实例方法的转发流程 和 OC-RunTime: 消息转发之实例方法的转发流程[实例讲解] 中分享了实例方法的转发流程.
今天分享如何对类方法进行消息的转发.
resolveClassMethod
NSObject 提供了 resolveClassMethod
来让开发者在里面动态添加一个类方法.
类方法的转发流程和实例方法转发的流程大致一样, 唯独不同的是需要重写的方法(NSObject中)的不一样.
当时我在写 Demo, 以为只需要将 resolveInstanceMethod
改为 resolveClassMethod
就万事大吉了即重写下面几个方法就可以解决问题, 事实证明这样是不行的.
- +resolveClassMethod
- -forwardingTargetForSelector
- -methodSignatureForSelector
- -forwardInvocation
- -doesNotRecognizeSelector:
网上很多博文并没有深入的探讨关于类方法转发的流程, 只是在介绍实例方法转发的流程的同时, 一笔带过类方法转发机制和流程.
通过对 NSObject.mm
源码的查看, 可以看到对应上面的几个方法都有类方法. 如下:
1 | 1. +resolveClassMethod |
重新这几个方法才是解决问题的关键.
现在我们重写 resolveClassMethod
, 如下.
ViewController.m
1 |
|
模拟调用
1 | - (void)viewDidLoad |
关于 SuppressPerformSelectorLeakWarning
可以参考 OC-RunTime: 消息转发之实例方法的转发流程[实例讲解].
将动态添加的方法让 proxyMethod
来执行, 显示结果达到预期.
1 | ---veryitman--- 1--- +resolveClassMethod |
创建被转发者
MZTempObj.m
1 | @implementation MZTempObj |
这里有类方法的一个实现 veryClassMethod
.
重写转发消息的函数
同理将 resolveClassMethod
修改一下, 为了保证流程继续.
示例代码如下:
1 | + (BOOL)resolveClassMethod:(SEL)sel |
执行后, 控制台输出日志:
1 | ---veryitman--- 1--- +resolveClassMethod. selector: veryClassMethod |
这里注意一下
将代码中
注意1
注意2
等部分可以自行打开测试一下, 然后将MZTempObj.m
中的类方法(+veryClassMethod)改为实例方法(-veryClassMethod), 也是可以的, 这样就达到了将类方法转发给实例方法的效果.
修改一下 forwardingTargetForSelector
中的实现, 可以看到 4, 5也会执行.
1 | + (id)forwardingTargetForSelector:(SEL)aSelector |
1 | ---veryitman--- 1--- +resolveClassMethod. selector: veryClassMethod |
同理我们可以得到类方法的消息转发流程图, 如下图所示:
推荐
OC-RunTime: 消息转发之实例方法的转发流程实例讲解
点击下载文中完整的 Demo.
扫码关注,你我就各多一个朋友~