
它就是一个函数指针,这是由编译器生成的。当你发起一个ObjC消息之后,最终它会执行的那段代码就是由这个函数指针指定的。而 IMP 这个函数指针就指向了这个方法的实现。
如果得到了执行某个实例某个方法的入口,我们就可以绕开消息传递阶段,直接执行方法,这在后面Cache中会提到。
你会发现 IMP 指向的方法与 objc_msgSend 函数类型相同,参数都包含 id 和 SEL 类型。每个方法对应一个 SEL 类型的方法选择器,而每个实例对象中的SEL对应的方法实现肯定是唯一的,通过id和 SEL 参数就能确定唯一的方法实现地址,而一个确定的方法也只有唯一的一组 id 和 SEL 参数。
Cache 定义如下:
Cache 为方法调用的性能进行优化,每当实例对象接收到一个消息时,它不会直接在 isa 指针指向的类的方法列表中遍历查找到能够响应的方法,因为每次都要查找效率太低了,而是优先在 Cache 中查找。
Runtime 系统会把被调用的方法存到 Cache 中,如果一个方法被调用,那么它有可能今后还会被调用,下次查找的收就会效率更高。
消息发送举例:
会被编译成:
objc_msgSend的具体流程如下:
通过 isa 指针找到所属的类
查找类的 cache 列表,如果没有则下一步
查找类的方法列表
如果能找到与选择子名称相符的方法,就跳至其实现代码
找不到的话,就沿着继承体系继续向上查找
如果能够找到与选择子名称相符的方法,就调至其实现代码
如果还没找到,就执行 “消息转发”
这里会给接收者最后一次机会把这个方法处理了,搞不定程序就会崩溃
在这里能做的比较现实的事就是:在触发消息前,先以某种方式改变消息内容,比如追加另外一个参数,或是改变消息等等。实现此方法时,如果发现某调用操作不应该由本类处理,可以调用超类的同名方法,则继承体系中的每个类都有机会处理该请求,知道 NSObject ,如果NSObject 搞不定,则还会调用 doesNotRecognizeSelector: 来抛出异常,此时你就会在控制台看到熟悉的unrecognized selector sent to instance..1

上面这4个方法均是模板方法,开发者可以override,由runtime来调用。最常见的实现消息转发,就是重写3和4。
方法调用的本质,就是让对象发送消息;
objc_msgSend,只有对象才能发送消息,因此以objc开头;
使用消息机制的前提,必须导入 #import<objc/message.h>
消息机制简单使用
消息机制的原理:对象根据方法编号SEL去映射表查找对应的方法实现。


简单来说就是将两个方法实现进行交换,比如系统自带的方法功能不够,我们想给系统自带的方法扩展一些功能,并且保持原有的功能,我们就可以使用Runtie,交换方法。
比如:我们想在 NSMutableArray 添加新对象的时候,进行置空判断。
如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。
给一个类声明属性,其实本质就是给这个类添加关联,并不是直接把这个值的内存空间添加到类存空间。
比如我们想给NSMutableArr类动态添加一个wce_name属性:
比如我们想把一个字典转化成对象,可以使用KVC,setValuesForKeysWithDictionary: ,但是必须要保证:模型中的属性和字典中key一一对应,如果不一致,就会报错。
所以,我们可以使用Runtime,遍历对象中的所有属性,根据模型的属性名,去字典中查找key,取出对应的值,给模型的属性赋值。建一个NSObject分类,专门字典转模型,以后所有的模型都可以通过这个分类转。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-58701-2.html
好听好看