原来这才是`Method-Swizzling`正确姿式

前言

昨天在翻阅DZNEmptyDataSet源码时发现了一些有趣的东西,如今和你们分享下:objective-c

  • Method-Swizzling不是在+load方法中
  • Method-Swizzling的方式并无使用method_exchangeImplementations()函数

下面一块儿来探索一番吧!函数

按需交换方法

这点比较好理解,直到须要的时候才去Swizzling,而不是在+load方法中。关于在+load方法中进行Method-Swizzling,这里有篇文章参考。下面是相关方法的截图。具体代码你们能够去GitHub围观。 spa

"很是规"的Swizzling

这点须要细说下。平时你们对于Method-Swizzling的印象大多停留在+load的阶段,忽然间,这个源码里找不到+load的影子,感受少了点啥。还好DZNEmptyDataSet留下了参考,让咱们一探究竟。3d

下面的观点来源于这里,你们能够自行参考code

从发送消息提及

假设如今有以下类实现: cdn

在咱们本身的实现方法swizzle_originalMethod中,经过[self swizzle_originalMethod];调用了原有的方法实现,这是你们一般的作法。blog

换成发送消息的写法就是:get

((void(*)(id, SEL))objc_msgSend)(self, @selector(swizzle_originalMethod));
复制代码

再看下没有Method-Swizzling以前,对原有实现的调用时什么样的:源码

((void(*)(id, SEL))objc_msgSend)(self, @selector(originalMethod));
复制代码

二者对比,很明显,咱们改变了发送消息时的第二个参数 - 方法选择子,也就是说这种Method-Swizzling技术留有“罪证”。若是原有方法实现依赖了这个方法选择子,它将没法正常工做。it

解决方案 - 使用method_setImplementation

直接给出代码:

咱们使用了method_setImplementation方法替换以前的实现,并使用静态变量保存了原有实现。这样就不会以前的问题了。达到了无痕的目的。

固然,这里的method_setImplementation也须要控制其执行的次数的!!!

结语

多翻看大神们的源码,仍是有好处的。😂😂😂

  • 若有错误,还请指出。共勉!
  • 您的喜欢是最大的赞扬。
相关文章
相关标签/搜索