iOS开发之旅--_isa和_imp指针

    

一、回顾_isa指针

之前谈到过isa指针,isa指针是一个指向所属类的指针,它标注着一个实例对象的真实类型。

在Object-C中消息机制是依靠objc_msgSend()这个函数发送消息,

objc_msgSend含两个参数:receiver、selector。即:objc_msgSend(receiver, selector);

而objc_msgSend通过isa指针,找到实例对象所属的类,也就找到了其全部父类,如下图所示:

iOS property 指针 ios isa指针_移动开发

一个方法被调用要经过的真实步骤是这样的:当我门向一个对象发送消息去调用他的方法时,objc_msgSend会根据该实例对象的isa指针去查找该对象的类,然后去查找该类的disptach table中的selector,如果找不到就会依次向上查找它的父类,并在其父类的dispatch table中查找相应的selector,直到NSObject类。一旦找到该selector,objc_msgSend会根据dispatch table中内存地址去调用该selector。这样实现message和selector在执行阶段的动态绑定。为了提高这种查找转发的效率。系统会把所有的selector内存地址和调用过的selector的内存地址缓存起来。而通过类的形式划分不同的缓存区域。每一个类的缓存区域会包括自己的selector和继承自父类的selector,在objc_msgSend去查找disptach table前,会先去检查该类的缓存。如果缓存命中,就直接调用selecotr。

二、了解_imp指针

imp是implementation的缩写,顾名思义imp指针是指向selector的具体实现的指针。在了解IMP指针之前,来探讨一个问题,现在需求是在不影响层级结构和尽量少改动的情况下,让项目中所有viewController的ViewDidLoad方法中打印自己的类型。了解Runtime的同学,可能会想到

method_exchangeImplementations(Method m1, Method m2)

iOS property 指针 ios isa指针_移动开发_02

这种方式很轻松的实现了我门的需求,但是作为一个优雅的程序员,就要做优雅的事情。下面就来imp指针。

首先要配置工程

进行如下配置:

iOS property 指针 ios isa指针_runtime_03

 

配置完成,直接上代码:

iOS property 指针 ios isa指针_iOS property 指针_04

 

使用imp指针更改方法实现成功。这样做比上一种方式更加优雅。

 

接下来探讨一下method_exchangeImplementations(Method m1, Method m2)方法的实现原理:

iOS property 指针 ios isa指针_runtime_05

从imp指针的地址打印来看貌似这个方法是将两个方法的imp指针做了互换。

 

经过这么多代码的测试,最终印证的还是那句话,imp指针是指向selector具体实现的指针。

附加一下真实imp的具体定义:

iOS property 指针 ios isa指针_iOS property 指针_06