1、回顾_isa指针程序员
以前谈到过isa指针,isa指针是一个指向所属类的指针,它标注着一个实例对象的真实类型。缓存
在Object-C中消息机制是依靠objc_msgSend()
这个函数发送消息,函数
objc_msgSend
含两个参数:receiver、selector。即:objc_msgSend(receiver, selector);测试
而objc_msgSend经过isa指针,找到实例对象所属的类,也就找到了其所有父类,以下图所示:spa
一个方法被调用要通过的真实步骤是这样的:当我门向一个对象发送消息去调用他的方法时,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。指针
2、了解_imp指针code
imp是implementation的缩写,顾名思义imp指针是指向selector的具体实现的指针。在了解IMP指针以前,来探讨一个问题,如今需求是在不影响层级结构和尽可能少改动的状况下,让项目中全部viewController的ViewDidLoad方法中打印本身的类型。了解Runtime的同窗,可能会想到对象
method_exchangeImplementations(Method m1, Method m2)blog
这种方式很轻松的实现了我门的需求,可是做为一个优雅的程序员,就要作优雅的事情。下面就来imp指针。继承
首先要配置工程
进行以下配置:
配置完成,直接上代码:
使用imp指针更改方法实现成功。这样作比上一种方式更加优雅。
接下来探讨一下method_exchangeImplementations(Method m1, Method m2)方法的实现原理:
从imp指针的地址打印来看貌似这个方法是将两个方法的imp指针作了互换。
通过这么多代码的测试,最终印证的仍是那句话,imp指针是指向selector具体实现的指针。
附加一下真实imp的具体定义: