美文网首页
objective-C之runtime第一篇

objective-C之runtime第一篇

作者: dominghao | 来源:发表于2018-02-27 15:06 被阅读5次

    网上查看了一些runtime的资料, 关于runtime是什么?这里想用自己的理解,简单点说:runtime是一套基于C语言的动态运行时机制. 这套机制实现了objective-C中一系列面向对象的基本用法, 比如类的定义,对象创建,方法调用.总之,它就是介于C语言和objective-C之前的一个抽象层.OK,就讲这么多.objective-C是一门动态的语言, 我想这里应该是最好的体现. 所有的方法,在执行之前,你都不知道,它的实现到底在哪里. 在运行的时候,你可以动态添加方法,实例变量,重定向方法的实现等.

    在objective-C中我们可以通过三种方式来与runtime进行交流.

    1. 当我们编写纯原生的objective-C代码时, 当这些代码经过编译,链接, 载入内存运行的时候, 会自动的经过runtime这套机制处理. 从我们创建对象到调用方法.都会最终映射到runtime上去处理.因为C语言不具备这种能力.runtime的作用就是这.弥补C的天生缺陷.而这一切,都是对程序员透明的, 自动的.
    2. 通过objective-C的基础类库Foundation中NSObject提供的方法.由于大多数类最终都是继承NSObject的,所以大多数类都可以通过使用NSObject提供的方法与runtime交流. 可以到NSObject.h里面去看看哪些方法.
    3. 直接使用runtime提供的函数.
      所有的runtime函数都在这里:https://developer.apple.com/documentation/objectivec/objective_c_runtime?language=objc

    • 下面来看看objective-C中使用最多的对象到底是什么?
      在objective-C中所有的类都继承自NSObject类.
    @interface NSObject <NSObject> {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wobjc-interface-ivars"
        Class isa  OBJC_ISA_AVAILABILITY;
    #pragma clang diagnostic pop
    }
    

    这里注意区分对象的区分. 类是一种逻辑描述, 是抽象的, 而对象是在内存中确实存在的,是具象的.定义一个类,只是在抽象层上描述一个对象是怎么样的.我们创建对象的时候,根据类(对象的描述)来分配内存,初始化最后得到了一个对象. 在objective-C中我们总是根据一个类的定义去创建该类所描述的对象.

    1. NSObject对象
      根据NSObject类,创建一个NSObject对象, 该对象(对象所属的类)有一个成员变量{Class isa;}. 下面我们看看,Class是什么?

      1.1 Class 是什么?
      Class是个结构体指针.详细定义见代码1.1

    代码1.1

    /// An opaque type that represents an Objective-C class.
    typedef struct objc_class *Class;
    
    struct objc_class {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    
    #if !__OBJC2__
        Class _Nullable super_class                              OBJC2_UNAVAILABLE;
        const char * _Nonnull name                               OBJC2_UNAVAILABLE;
        long version                                             OBJC2_UNAVAILABLE;
        long info                                                OBJC2_UNAVAILABLE;
        long instance_size                                       OBJC2_UNAVAILABLE;
        struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
        struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
        struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
        struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
    #endif
    
    } OBJC2_UNAVAILABLE;
    /* Use `Class` instead of `struct objc_class *` */
    

    忽略掉所有的预编译指令, 回到代码上来, 暂且就认为Class是个结构体指针.

    接着上面的1说:我们知道内存中的一个NSObject对象,里面有个isa指针变量,它指向一个结构体.OK , 指针不太明白,暂且这么理解:也就是说根据isa里面提供的值(其实就是一个地址),我们可以在内存中找到一个struct Class 类型的结构体. 具体是什么样的,请看代码1.1

    • 下面我们看看,这个isa所指向的结构体具体是什么?
      isa指针:指向该对象所属类型的类型对象(Class Object)。在Objective-C中,类也是用对象来表示的,而类的isa指针指向它的metaclass(存储静态成员变量和类方法)。
      super_class指针:指向父类。
      name:类名称。
      version:类的版本信息。
      info:运行期使用的标志位,比如0x1(CLS_CLASS)表示该类为普通class,0x2(CLS_META)表示该类为 metaclass。
      instance_size:实例大小,即内存所占空间。
      ivars:指向成员变量列表的指针。
      methodLists:根据标志位的不同可能指向不同,比如可能指向实例方法列表,或者指向类方法列表。
      cache:因为Objective-C的消息转发需要查找dispatch table甚至可能需要遍历继承体系,所以缓存最近使用的方法。
      protocols:类需要遵守的协议。

    由NSObject对象的isa指针指向的结构体可知,这个结构体描述的是关于NSObject类的信息, 可称作objc_class 结构体.它描述了NSObject类的成员列表,方法列表,所遵守的协议列表等关于该类的信息.

    在objc_class结构体中,也有一个isa指针,指向一个和自己相同类型的结构体. 这其实不难理解, 对象相关的逻辑描述信息,存放在该对象所属类的那个结构体中.也即是objc_class结构体中. 但是在objective-C中, 类本身也是一个特殊的对象,所以其中也有一个isa指针. 或者说objc_class中也有一个isa指针, 我们也可以把它当做一个对象来看待.

    1. objc_class中的isa指针又指向哪里呢?
      指向该类的元类(metaclass).我们可以简单把objc_class看成是其成员变量isa指针所指向元类的实例. 同理,元类是描述这个类的具体信息的,属于更高一层的抽象.
      到这里已经差不多了.metaclass 中的isa指针又指向哪里呢, 答:指向根元类.根元类的isa指向自己.也就是说所有的对象,类,元类的最终归宿都是跟元类.


      实例 类 元类

    好吧, 我认为把我所知道的都写明白了. 关于消息的处理转发, 以及
    runtime提供的一些函数的具体使用.下一篇再说.

    引用:http://blog.csdn.net/oqqquzi1234567/article/details/43268947

    相关文章

      网友评论

          本文标题:objective-C之runtime第一篇

          本文链接:https://www.haomeiwen.com/subject/bsqmxftx.html