-
Method-Swizzling是什么
method-swizzling的含义是方法交换,其主要作用是在运行时将一个方法的实现替换成另一个方法的实现,这就是我们常说的iOS黑魔法,(所谓的交换就是改掉sel和imp的对应关系如下图) -
Method-Swizzling相关Api解释
class_getInstanceMethod通过sel获取实例方法class_getClassMethod通过sel获取类方法method_getImplementation获取一个方法的实现method_setImplementation设置一个方法的实现method_getTypeEncoding获取方法实现的编码类型class_addMethod添加方法实现class_replaceMethod用一个方法的实现,替换另一个方法的实现method_exchangeImplementations交换两个方法的实现
-
Method-Swizzling坑点
-
执行一次问题
设想一下如果方法交换执行了两次那么结果是第一次做了一次交换没问题,但是在第二次交换的时候就会将第一次交换的结果还原回去,所以一般mehod-swizzling写在load方法中,但是load方法也不免认为继续调用,所以有可能出现调用多次情况,在针对于这周情况可以通过单例设计原则,实现方法酯交换一次如下代码: -
需要交换的方法子类没有实现但是父类实现了的问题
举例父类中含有personInstanceMethod方法子类中含有lg_studentInstanceMethod方法现在对这两个方法进行交换(我们知道如果在子类中没有查找到方法的实现回到父类中继续查找所以结果是父类的方法和子类的方法进行了交换)如下图对应代码实现
应为子类中含有
lg_studentInstanceMethod的实现所以子类调用personInstanceMethod没问题,但是父类并没有lg_studentInstanceMethod方法的实现方法的查找只会沿着父类向上查找不会查找子类的方法列表所以当父类调用的时候直接崩溃相应解决方案:
交换之前先查找当前类是否有对应的方法实现,如果没有则方法替换如果存在则交换方法如下代码当然这里如果要交换的方法当前类中没有可以添加一个空实现,然后再交换方法,这两种方案都行可按照项目需求自定义
解决方案优化
当然也存在传入的 -
子类也没有实现父类也没有实现的情况
这种情况class_getInstanceMethod就获取不到值了,所以此时我们只需要判断class_getInstanceMethod是否为空如果是空则添加一个空的方法实现再走上述步骤的流程如下代码
-