今天在项目中遇到个问题,在两个load方法中,都对UIViewController的viewWillAppear:方法进行了交换。那么问题来了,两个方法交换到底哪个有效果,还是都有效果?于是我就写了个demo,对此进行验证。
先来看demo
图一是目录结构(我随便写的一个testDemo,里面有一些无关的类),图一中,我依次一共创建了五个UIViewcontroller的分类,然后每个类都进行了方法交换,如图二:
运行之后,控制台打印log如图三:
我们看到,五个分类,五次方法交换,最终只打印了一次,而且打印的是UIViewController+Swizzle1分类中的方法交换,说明,方法交换之后,只有第一个方法有效,其他四个均无效;那么问题来了,哪个方法有效、哪个方法无效取决于什么呢?思索片刻之后,我找到了这个地方,看图四:
我们看到Compile Sources中实现文件的顺序,这个顺序其实也是文件的添加顺序,我们推测,此顺序决定文件加载顺序,也就决定了load 方法执行顺序;既然如此,我们打印一下五个分类的load方法执行顺序,看结果如何(图五):
现在结果已经很明显了,后添加的文件,先加载,按照Compile Sources目录顺序执行load方法,于是,经过5、4、3、2、1方法交换之后,最终,UIViewController+Swizzle1分类的交换方法将之前交换的方法覆盖,执行它的方法实现,所以,我们可以初步得出结论,load方法的执行顺序按照Compile Sources顺序。
但是,毕竟是抽样测试,为了结论的准确性,我们决定在此目录中所有类中都打印load方法,看一看执行顺序,如图六:
由于分类的load方法后于类的load方法执行,所以,显而易见,我们的结论是正确的,load方法的执行顺序由Compile Sources决定。所以,以后我们在实际使用过程中,要注意,不要在多个分类load方法同时Method Swizzling一个方法的实现,这样会导致之前的交换失效,如果真的这么做了,那么最终的结果会根据compile source决定。