ACCESS自在学习之三——IMP指针的法力

或许大家一向看到有成千上万仇人在Runtime相关著作中牵线IMP指针的概念,那么IMP究竟有什么样实际功能吗?让我们先从一个函数看起来。

Method Swizzling

假若对Runtime有一定了解的话,一定听说过仍然用过那一个函数:

void method_exchangeImplementations(Method m1, Method m2)

它一般称为method
swizzling,算是ObjC的”黑魔法”了,效能就是在程序运行期间动态的给五个艺术互换实现,比如有那样一种采纳境况:


咱俩的顺序中有不少个ViewController,我想在对项目变更最小的场所下,在当每个Controller执行完ViewDidLoad未来就在控制台把团结的名字打印出来,方便我去做调试或者领悟项目布局。


有很多爱人会这么说,让抱有控制器都连续一个BaseController不就可以了啊?我在这边要解释一下这样做的先天不足:假诺你的花色里有成百上千Controller的话,你就需要把品种里凡是没有继续自BaseController的各种Controller都做三遍修改了,而且擅自改变层级结构会发生意外的荒唐。

骨子里大家的目的哪怕重写ViewDidLoad的措施,并在她的艺术最终加上几句Log,所以大家需要给UIViewController建立一个category,因为大家精晓,如若在Catagory中重写一个主意,就会覆盖它的原本艺术实现,不过,这样做未来就从未有过章程调用系统原本的办法,因为在一个方法里调用自己的方法会是一个死循环。所以我们的解决办法就是,其余写一个主意来和viewDidLoad“互换”,这样表面调用viewDidLoad就会调到新建的这些形式中,同样,我们调用新建的措施就会调用到系统的viewDidLoad中了。

Screen Shot 2015-07-15 at 11.10.02 AM.png

IMP指针

骨子里,还有一种更加简明的办法可以让大家办到相同的目标,运用IMP指针,IMP就是Implementation的缩写,顾名思义,它是指向一个办法实现的指针,每一个主意都有一个对应的IMP,所以,我们得以一直调用方法的IMP指针,来防止方法调用死循环的问题。

调用一个IMP的方法和调用普通C函数相同,比如:

id returnObjc = someIMP(objc,SEL,params...);

可是只要您的项目并未做其他安排的话这样调用编译器是不会经过的,大家来看一下先它的概念:

if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
else
typedef id (*IMP)(id, SEL, ...); 
endif

在默认情形下您的工程是开拓这一个布局的

Screen Shot 2015-07-15 at 2.29.56 PM.png

这种场地下IMP被定义为无参数无再次回到值的函数。所以你需要到工程里搜索到那一个选项并把它倒闭。那样的分神就是,每一遍使用,你都亟需修改工程安排,所以这里自己再介绍此外一种艺术:重新定义一个和有参数的IMP指针相同的指针类型,在获取IMP时把它强转为此类型。那样运用IMP指针后,就不需要出色的给ViewController写新的法子:

Screen Shot 2015-07-16 at 9.56.19 AM.png

再有一个地点大家需要留意,假设这么平昔调用IMP的话就会生出经典的EXC_BAD_ACCESS错误,大家定义的IMP指针是一个有重返值的品种,而实际上我们获取的viewDidLoad这么些方法是未曾重回值的,所以大家需要新定义一个和IMP相同类此外函数指针比如VIMP,把她的重回值定位Void,这样一旦您改改的主意有重回值就用IMP,没有重回值就用VIMP。

Screen Shot 2015-07-15 at 5.49.54 PM.png

Screen Shot 2015-07-15 at 3.36.05 PM.png

值得注意的是,假如你重写的艺术有再次回到值,不要遗忘在最终做return。

总结

实际上一贯调用一个形式的IMP指针的功用是凌驾调用方法本身的,所以,假使您有一个适中的火候获取到方法的IMP的话,你可以试着调用它。
这是只是IMP使用的景观之一,它还有许多效益,希望我们多多发现。

相关文章