Objetive-C最基本的的东西就是它的消息机制。Objective-C运行时的最基本的东西就是 objc_msgSend, 它就是负责发送一个消息给对象的C函数。
objc_msgSend的返回类型是id. 如果你需要 让一个方法调用, 返回一个原始的对象(或者C结构体)而不是 对象指针, 那应该怎么办呢?
执行下面人为捏造的代码(因为一般不会直接调用msgSend),会返回一个编译器错误,因为类型不匹配
UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; CGRect rect = objc_msgSend(view, @selector(frame));
如果你将第2行,改成 [view frame]
编译器 不会 把它转换成 msgSend, 而是调用 objc_msgSend_stret
objc_msgSend_stret是一个objc_msgSend的替代版本, 用来返回一个结构体。stret就是 STruct RETurn的缩写。
另外一个相关的objc_msgSend_fret 返回一个Floating-pointer
objc_msgSend_stret
如果待发送的消息要返回结构体,那么可交由此函数处理。只有当CPU的寄存器能够容纳得下消息返回类型时,这个函数才能处理此消息。若是返回值无法容纳于CPU寄存器中(比如说返回的结构体太大了),那么就由另一个函数执行派发。此时,那个函数会通过分配在栈上的某个变量来处理消息所返回的结构体。
objc_msgSend_fpret
如果消息返回的是浮点数,那么可交由此函数处理。在某些架构的CPU中调用函数时,需要对“浮点数寄存器”(floating-point register)做特殊处理,也就是说,通常所用的objc_msgSend在这种情况下并不合适。这个函数是为了处理x86等架构CPU中某些令人稍觉惊讶的奇怪状况。
objc_msgSendSuper
如果要给超类发消息,例如[super message:parameter],那么就交由此函数处理。也有另外两个与objc_msgSend_stret和objc_msgSend_fpret等效的函数,用于处理发给super的相应消息。
1、为了性能,objc_msgSend用汇编写成。存在于objc-msg-x86_64.s中。
2、在上图代码中可以看到,objc_msgSend被分为2个过程:1)在cache中寻找SEL。2)在MethodTable寻找SEL。
3、CacheLookup中,不断地拿SEL与cache中的缓存比较,比较失败,则跳转到 LCacheMiss标签继续在MethodTable中搜索。
如果想手动查找cache,则需要调用_cache_getimp函数(汇编实现),此函数是个对外接口层,用于保存与准备环境。
_cache_getImp在头文件中objc-private.h中,链接后objc/c代码可以直接调用。
4、MethodTableLookup 是个接口层宏,主要用于保存环境与准备参数,来调用 __class_lookupMethodAndLoadCache3函数(此函数实现于objc-class.mm)。
5、__class_lookupMethodAndLoadCache3函数也是个接口层(C编写),此函数提供相应参数配置,实际功能在lookUpMethod函数中。