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

前言

昨天在翻阅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也需要控制其执行的次数的!!!

结语

多翻看大神们的源码,还是有好处的。???

  • 如有错误,还请指出。共勉!
  • 您的喜欢是最大的赞赏。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值