OC运行时简单运用--3.1 动态交换方法实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WangErice/article/details/51211328

在项目开发过程中,总是能遇到一些重复代码,却不得不一遍遍重写,有些还特别容易产生变动,然后你又不得不一个个找到它们,并手动一个个去修改,很容易会出现遗漏或者手残改错的情况。或许使用继承在基类中书写共同的方法可以在一定程度上减少代码修改的过程,可是并不能保证所有的控制器都继承自同一个基类,而且继承会产生很多不必要的内存冗余。现在我们尝试使用运行时机制来做一个处理这样的问题。

了解更多请点击这里(英文链接)   (中文链接)

假设场景场景:我们需要知道在程序运行过程中每个页面出现的次数,并为每一个控制器的根视图赋上应用专有的背景色。

1.创建UIViewController的Category,并引入<objc/rumtime.h>头文件;

2.并重写类方法+(void)load{}方法,并在方法中,使用dispatch_once创建交换事件;

首先使用class_addMethod和class_replaceMethod方法交换两个方法的实现,如果交换出现错误导致交换失败,则使用method—_exchangeImplementation方法直接交换两个方法的实现,是一种确保万无一失的安全措施。

至于UIInputWindowController就不太清楚是个什么鬼了,可以确定的是该控制器的显示等级非常高,几乎在所有可显示视图的最上边,应该是系统自定义输入输出有关系,如果不排除该类控制器的话,你就会神奇的发现所有的视图都消失了。

[self _viewDidLoad];这个方法的调用乍一看好像是死循环无限递归了,其实此时的该方法的实现已经被替换成了原始的的方法实现,所以调用该方法是调用的是原来的实现。需要注意的是,几乎所有的动态替换都会需要调用原来的实现,以确保内部框架的机制不被破坏。

另外,由于OC语言本身没有命名空间的概念,所以在使用Category进行方法动态替换的时候有可能会因为命名冲突而造成方法的覆盖,由于Method Swizzling对类的全局都有影响会造成你意想不到的意外,所以建议使用类C的语言进行替换,以下代码供参考。

扫描二维码关注公众号,回复: 6632017 查看本文章

既然可以交换实例方法的交换,那也一定可以实现类方的交换,只是类方法保存在类所对应的元类中,所以进行交换时需要注意操作的对象是当前类的元类,而不是当前类,大致过程如下(注意黄色箭头部分)

类。

猜你喜欢

转载自blog.csdn.net/WangErice/article/details/51211328