iOS 底层探索篇 —— KVC 底层原理
1. Method Swizzling的坑与应用
1.1 method-swizzling 是什么?
Method-Swizzling实际就是更换方法所对应的实现函数,其主要作用是在运行时将一个方法的实现替换成另一个方法的实现,这就是我们常说的iOS黑魔法
。method-swizzling最常用的应用是防止数组、字典等越界崩溃
。
下面的代码是否会无限递归呢?答案是不会的,因为交换方法后,lg_studentInstanceMethod
实际上是通过[self personInstanceMethod]
调用的,而 [self lg_studentInstanceMethod]
则是调用 personInstanceMethod
,所以不会无限递归。
1.2 坑点
坑点1:method-swizzling使用过程中的确保执行一次
所谓的一次性就是:mehod-swizzling
写在load方法中,而load方法会主动调用多次
,这样会导致方法的重复交换
,无法确保是否交换成功。
如何解决这个问题呢?
解决方案
可以通过单例设计原则,在OC中可以通过dispatch_once
实现单例,这样就可以使方法交换只执行一次
。
坑点2:子类没有实现,父类实现了
如果交换的方法在子类没有实现,在父类里面实现了,那么交换的时候会不会报错呢?
运行后发现报错了。这是因为,personInstanceMethod
已经被交换成了lg_studentInstanceMethod
。而在lg_studentInstanceMethod
里面调用了[self lg_studentInstanceMethod]
,而LGPerson
里面是没有lg_studentInstanceMethod
方法的,所以抱错。
为什么要有[self lg_studentInstanceMethod]呢?这是因为如果在满足一定条件下,那么就还会走原有的逻辑。比如数组越界,如果index < array.count, 那么就还走原有的逻辑。
解决方案
先通过class_addMethod
尝试给自己添加要交换的方法,如果添加成功,即类中没有这个方法,则通过class_replaceMethod
进行替换,如果添加失败则代表有这个方法,正常进行method_exchangeImplementations
。