zoukankan      html  css  js  c++  java
  • 第十一条理解objc_masgSend的作用

    Objetive-C最基本的的东西就是它的消息机制。Objective-C运行时的最基本的东西就是 objc_msgSend, 它就是负责发送一个消息给对象的C函数。

     
    当你写下面这样的代码时:  [tableView cellForRowAtIndexPath:indexPath];
     
    编译器实际上把它转换成下面这样的C函数调用  objc_msgSend(tableView, @selector(cellForRowAtIndexPath:), indexPath);
     

    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

     
    函数声明
    void objc_msgSend_stret(void *stretAddr, id theReceiver, SEL theSelector, ....)
     
    几个特殊方法

    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函数中。

      

     6、lookUpMethod函数实现遍历method_list_t,从子类开始,一直遍历到根类。此函数代码较大,不贴图了。文件在objc-class中。
  • 相关阅读:
    数据结构-树与二叉树-思维导图
    The last packet successfully received from the server was 2,272 milliseconds ago. The last packet sent successfully to the server was 2,258 milliseconds ago.
    idea连接mysql报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property
    redis学习笔记
    AJAX校验注册用户名是否存在
    AJAX学习笔记
    JSON学习笔记
    JQuery基础知识学习笔记
    Filter、Listener学习笔记
    三层架构学习笔记
  • 原文地址:https://www.cnblogs.com/xsyl/p/5817846.html
Copyright © 2011-2022 走看看