前言
昨天在翻阅DZNEmptyDataSet
源码时发现了一些有趣的东西,现在和大家分享下:
Method-Swizzling
不是在+load
方法中Method-Swizzling
的方式并没有使用method_exchangeImplementations()
函数
下面一起来探索一番吧!
按需交换方法
这点比较好理解,直到需要的时候才去Swizzling
,而不是在+load
方法中。关于在+load
方法中进行Method-Swizzling
,这里有篇文章参考。下面是相关方法的截图。具体代码大家可以去GitHub围观。
"非常规"的Swizzling
这点需要细说下。平时大家对于Method-Swizzling
的印象大多停留在+load
的阶段,突然间,这个源码里找不到+load
的影子,感觉少了点啥。还好DZNEmptyDataSet
留下了参考,让我们一探究竟。
下面的观点来源于这里,大家可以自行参考
从发送消息说起
假设现在有如下类实现:
在我们自己的实现方法swizzle_originalMethod
中,通过[self swizzle_originalMethod];
调用了原有的方法实现,这是大家通常的做法。
换成发送消息的写法就是:
((void(*)(id, SEL))objc_msgSend)(self, @selector(swizzle_originalMethod));
再看下没有Method-Swizzling
之前,对原有实现的调用时什么样的:
((void(*)(id, SEL))objc_msgSend)(self, @selector(originalMethod));
两者对比,很明显,我们改变了发送消息时的第二个参数 - 方法选择子
,也就是说这种Method-Swizzling
技术留有“罪证”。如果原有方法实现依赖了这个方法选择子
,它将无法正常工作。
解决方案 - 使用method_setImplementation
直接给出代码:
我们使用了method_setImplementation
方法替换之前的实现,并使用静态变量
保存了原有实现。这样就不会之前的问题了。达到了无痕
的目的。
当然,这里的method_setImplementation
也需要控制其执行的次数的!!!
结语
多翻看大神们的源码,还是有好处的。😂😂😂
注
- 如有错误,还请指出。共勉!
- 您的喜欢是最大的赞赏。