内容来源:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html
The objc_msgSend Function
在objective-C里,在运行时前,消息并不和方法实现绑定.也就是说,在运行前只知道方法名,并不知道方法具体实现(方法体).
编绎器会把
[receiver message]
转成
objc_msgSend(receiver, selector)
如果有参数
objc_msgSend(receiver, selector, arg1, arg2, ...)
这个消息方法做以下的动态绑定:
1.这会先找到这个selector所对应的方法实现(方法体).
2.它会把接收方法的对象以及所有参数传入方法实现.
3.最后,它把程序的最后的计算结果,作回return 值传回.
注意:编译器会生成消息传递方法(objc_msgSend),你自己决不能直接调用.
每一个类结构(class structure)包含两部分:
1:一个指向你类的指针.
2:一个类 分配表(dispatch table).这个表,应该是键值对应关系,键是方法selector,值是方法具体实现的地址.通过个地址可以找到方法体.
当一个新对象创建时,内存会被分配,并且它的实例亦是也会被初始化.第一个对象变量是指向对它类结构(class structure)的指针.这个指针被叫作 "isa",让对象能访问它的类,通过类,能访问所有它继承的类.
"isa" 是struct objc_object类型的指针
方法的层级调用,
当一个方法传给对象,对象会通知道isa找到类结构,类结构里有dispatch table,在table里找selector,如果没找到,会找父类的dispatch table.直到找到或到达NSObject.一旦找到方法就会调用,并传入接收c对象的数据结构.
为了加快消息传递的进程,每个类都有自己的缓存,它可以包含继承的方法,就像这个方法是在本类里定义的一样.在搜索dispatch table之间,会先检查接收方法的类的方法缓存,如果有就直接调用,速度只比一个函数调用稍微慢一些.一旦一个工程运行的足够长,它所有的方法都在缓存里找到.缓存大小也会动态的增加,以至于可以容纳亲的消息.
当objc_msgSend找到方法的具体实现,它会调用程序并传入所有的参数.这个包含两个隐藏的参数
1:接收对象本身.
2:方法的selector