事件背景:打算在UIButton的扩展类里面 hook intrinsicContentSize 方法,然后直接在+load的时候调用method_exchangeImplementations把自己的自定义xx_intrinsicContentSize方法跟现有的方法列表里面的交换,然后发生崩溃,但是UILabel就不会。
事件的原因:UIButton并没有重写基类UIView的intrinsicContentSize方法,所以直接把基类UIView的方法和UIButton扩展的方法交换了,当其他UIView的子类调用intrinsicContentSize的时候就会调用到UIButton的xx_intrinsicContentSize扩展方法,但是当前类方法列表肯定是没有的,所以就崩溃了,本质原因是,应该对本类的这方法做hook,不应该hook到基类。UILabel的扩展做同样的事情为什么不会崩溃呢,因为UILabel重写了intrinsicContentSize方法,并不是基类的实现,所以直接替换只是一次对UILabel普通的hook做了一些额外的事情,而且这个hook的方法是在类别里面,可以调得到。
解决办法是:
先调用class_addMethod尝试为当前类UIButton添加intrinsicContentSize方法,class_addMethod
这个方法的实现会覆盖父类的方法实现,但不会取代本类中已存在的实现,如果本类中包含一个同名的实现,则函数会返回NO。以保证修改的就是当前类。只要当前类有这个方法,以后对这个类的各种类别+load里面的hook就可以按照Build Phases的顺序hook,做一些自己自定义的额外的事情了。