zoukankan      html  css  js  c++  java
  • iOS开发日记17-runtime基础篇

    今天博主有一个runtime基础的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步.

    Objective-C runtime是一个运行时库,主要是由C语言和汇编语言写成,为C语言添加面向对象的能力而创造了Objective-C。这意味着它可以加载类信息,进行方法派发以及方法转发等等。Objective-C 运行时最重要的就是为Objective-C语言的面向对象特性的实现提供了所有的基础支撑.

    那么,runtime具体究竟是什么呢?相信各位看官百度了很多文章后,发现十篇有九篇都看不懂,这时因为有很多基础的东西我们并不了解,今天博主就和大家分享一下,runtime基础篇

    我们写的代码在程序运行过程中都会被转化成runtime的C代码执行,例如[xxxxxx doSomething];会被转化成objc_msgSend(xxxxxx, @selector(doSomething));

    OC中一切都被设计成了对象,我们都知道一个类被初始化成一个实例,这个实例是一个对象。实际上一个类本质上也是一个对象,在runtime中用结构体表示。

    相关的定义:

    /// 描述类中的一个方法
    typedef struct objc_method *Method;
    /// 实例变量
    typedef struct objc_ivar *Ivar;
    /// 类别Category
    typedef struct objc_category *Category;
    /// 类中声明的属性
    typedef struct objc_property *objc_property_t;

    类在runtime中的表示

    //类在runtime中的表示
    struct objc_class {
      Class isa;//指针,顾名思义,表示是一个什么,
      //实例的isa指向类对象,类对象的isa指向元类
    #if !__OBJC2__
      Class super_class;  //指向父类
      const char *name;  //类名
      long version;
      long info;
      long instance_size
      struct objc_ivar_list *ivars //成员变量列表
      struct objc_method_list **methodLists; //方法列表
      struct objc_cache *cache;//缓存
      //一种优化,调用过的方法存入缓存列表,下次调用先找缓存
      struct objc_protocol_list *protocols //协议列表
      #endif
    } OBJC2_UNAVAILABLE;
    /* Use `Class` instead of `struct objc_class *` */

    相信很多看官看到这里的时候,就已经有想关屏幕的冲动了,下面给大家分享一下isa指针和meta class(元类)

    每个对象都会有一个它所属的类。这是面向对象的基本概念,但是在OC中,这对所有数据结构有效。任何数据结构,只要在恰当的位置具有一个指针指向一个class,那么,它都可以被认为是一个对象。
    在OC中,一个对象所属于哪个类,是由它的isa指针指向的。这个isa指针指向这个对象所属的class。

    isa:是一个Class 类型的指针. 每个实例对象有个isa的指针,他指向对象的类,而Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是:元类(meteClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root meteClass).根元类的isa指针指向本身,这样形成了一个封闭的内循环

    一个OC的类其实也是一个对象,意思就是你可以向一个类发送消息。
    NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];
    在这个例子中,defaultStringEncoding 被发送给了NSString类。因为每一个OC的类本身也是一个对象。也就是说Class的数据结构必然也是以isa指针开始的在二进制级别上与objc_object是完全兼容的。然后一个类结构的下一个字段一定是一个指向super class的指针(或者指向nil,对于基类而言)。
    一个类如何定义有很多方法,依赖于你的运行时库版本,但是不管哪种方法,他们都是以一个isa作为第一个字段,接着是superclass字段

    为了可以调用类方法,这个类的isa指针必须指向一个包含这些类方法的类结构体。
    这样就引出了meta-class的概念:meta-class是一个类对象的类。
    简单解释下:
           当你向一个对象发送消息时,runtime会在这个对象所属的那个类的方法列表中查找。
           当你向一个类发送消息时,runtime会在这个类的meta-class的方法列表中查找。

    meta-class之所以重要,是因为它存储着一个类的所有类方法。每个类都会有一个单独的meta-class,因为每个类的类方法基本不可能完全相同
    meta-class,就像Class一样,也是一个对象。你依旧可以向它发送消息调用函数,自然的,meta-class也会有一个isa指针指向其所属类。所有的meta-class使用基类的meta-class作为他们的所属类。具体而言,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己所属的类。

    根据这个规则,所有的meta-class使用基类的meta-class作为它们的类,而基类的meta-class也是属于它自己,也就是说基类的meta-class的isa指针指向它自己。
    就像一个类使用super_class指针指向自己的父类一样,meta-class的super_class会指向类的super_class的meta-class。一直追溯到基类的meta-class,它的super_class会指向基类自身

    这样一来,整个继承体系中的实例、类和meta-class都派生自继承体系中的基类。对于NSObject继承体系来说,NSObject的实例方法对体系中所有的实例、类和meta-class都是有效的;NSObject的类方法对于体系中所有的类和meta-class都是有效的
    meta-class是类对象的类,每个类都有自己单独的meta-class。所有的类对象并不会属于同一个meta-class。

    meta-class要保证类对象具有继承体系中基类的所有实例和类方法,以及继承体系中的所有中间类方法。对于所有NSObject继承体系下的类,NSObject的实例方法和协议方法对他们和他们meta-class的对象都要有效。
    所有的meta-class使用基类的meta-class作为自己的基类,对于顶层基类的meta-class也是一样,只是它指向自己而已
     
    还有几篇文章可以增加各位对runtime的理解
    http://quotation.github.io/objc/2015/05/21/objc-runtime-ivar-access.html
    http://www.jianshu.com/p/425a39d43d16?utm_campaign=maleskine&utm_content=note&utm_medium=writer_share&utm_source=weibo
    http://mp.weixin.qq.com/s?__biz=MjM5NTIyNTUyMQ==&mid=208927760&idx=1&sn=30b9caecba709553e463d719668454ae&scene=2&from=timeline&isappinstalled=0#rd

  • 相关阅读:
    Linux内存管理(text、rodata、data、bss、stack&heap)
    名词解释:Linux内存管理之RSS和VSZ
    数据库对比:选择MariaDB还是MySQL?
    linux 下 pip 安装教程
    Mysqlbinlog工具及导出数据并转换编码导入
    运维监控系统之Open-Falcon
    MySQL binlog格式解析
    理解和配置Out of memory: Kill process
    mysql优化——explain详解
    mysql性能优化-慢查询分析、优化索引和配置 (慢查询日志,explain,profile)
  • 原文地址:https://www.cnblogs.com/Twisted-Fate/p/4801317.html
Copyright © 2011-2022 走看看