自在上之三——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使用的情景之一,它还有好多企图,希望大家多多发现。

相关文章