美文网首页
底层原理(五)------Class详解

底层原理(五)------Class详解

作者: SwordDevil | 来源:发表于2021-05-25 15:24 被阅读0次

    Objective-C是一门动态性比较强的编程语言,跟C、C++等语言有着很大的不同
    Objective-C的动态性是由Runtime API来支撑的
    Runtime API提供的接口基本都是C语言的,源码由C\C++\汇编语言编写

    一、isa详解

    • 在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的内存地址
    • 从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息


    二、位运算

    mask 掩码
    “& 与” 按位与运算 如果都是1 就输出1 ,如果不都是1 就输出0
      0000 0111
    & 0000 0001
    -------------
      0000 0001
    tall      就是0000 0001  也就是1
    rich      就是0000 0010  也就是2
    handsome  就是0000 0100  也就是4
    "| 或"按位或运算 如果是1 其他都是1
      0000 0101
    | 0000 0011
    -------------
      0000 0111
    ”~“按位取反
    
    普通写法
    #import "MJPerson.h"
    
    // &可以用来取出特定的位
    
    // 0000 0111
    //&0000 0100
    //------
    // 0000 0100
    
    // 掩码,一般用来按位与(&)运算的
    //#define MJTallMask 1
    //#define MJRichMask 2
    //#define MJHandsomeMask 4
    
    //#define MJTallMask 0b00000001
    //#define MJRichMask 0b00000010
    //#define MJHandsomeMask 0b00000100
    
    #define MJTallMask (1<<0) // 1左移0位
    #define MJRichMask (1<<1) // 1左移1位
    #define MJHandsomeMask (1<<2) // 1左移2位
    
    @interface MJPerson()
    {
        char _tallRichHansome;
    }
    @end
    
    @implementation MJPerson
    
    
    // 0010 1010
    //&1111 1101
    //----------
    // 0010 1000
    
    - (instancetype)init
    {
        if (self = [super init]) {
            _tallRichHansome = 0b00000100;
        }
        return self;
    }
    
    - (void)setTall:(BOOL)tall
    {
        if (tall) {
            _tallRichHansome |= MJTallMask;
        } else {
            _tallRichHansome &= ~MJTallMask; // ~ 按位取反 不是|
        }
    }
    
    - (BOOL)isTall
    {
        return !!(_tallRichHansome & MJTallMask);
    }
    
    - (void)setRich:(BOOL)rich
    {
        if (rich) {
            _tallRichHansome |= MJRichMask;
        } else {
            _tallRichHansome &= ~MJRichMask;
        }
    }
    
    - (BOOL)isRich
    {
        return !!(_tallRichHansome & MJRichMask);
    }
    
    - (void)setHandsome:(BOOL)handsome
    {
        if (handsome) {
            _tallRichHansome |= MJHandsomeMask;
        } else {
            _tallRichHansome &= ~MJHandsomeMask;
        }
    }
    
    - (BOOL)isHandsome
    {
        return !!(_tallRichHansome & MJHandsomeMask);
    }
    
    @end
    
    结构体位域写法
    // !!(_tallRichHansome & MJTallMask) 也可以不这么写,直接写(_tallRichHansome & MJTallMask),但是需要位域1改为2,也就是char rich : 2;
    #import "MJPerson.h"
    
    //#define MJTallMask (1<<0)
    //#define MJRichMask (1<<1)
    //#define MJHandsomeMask (1<<2)
    
    @interface MJPerson()
    {
        // 位域
        struct {
            char tall : 1; // : 1 位域
            char rich : 1;
            char handsome : 1;
        } _tallRichHandsome;
        // 0x 0000 0000 先写的在后边 也就是tall在倒数第一个0,rich在倒数第二个0,handsome在倒数第三个0
    }
    @end
    
    @implementation MJPerson
    
    - (void)setTall:(BOOL)tall
    {
        _tallRichHandsome.tall = tall;
    }
    
    - (BOOL)isTall
    {
        return !!_tallRichHandsome.tall;
    }
    
    - (void)setRich:(BOOL)rich
    {
        _tallRichHandsome.rich = rich;
    }
    
    - (BOOL)isRich
    {
        return !!_tallRichHandsome.rich;
    }
    
    - (void)setHandsome:(BOOL)handsome
    {
        _tallRichHandsome.handsome = handsome;
    }
    
    - (BOOL)isHandsome
    {
        return !!_tallRichHandsome.handsome;
    }
    
    @end
    
    union共用体写法
    #import "MJPerson.h"
    
    #define MJTallMask (1<<0)
    #define MJRichMask (1<<1)
    #define MJHandsomeMask (1<<2)
    #define MJThinMask (1<<3)
    
    @interface MJPerson()
    {
        union {
            int bits;
            
            struct { // 只是增加可读性,不会影响共用体所占字节大小,可以删掉
                char tall : 4;
                char rich : 4;
                char handsome : 4;
                char thin : 4;
            };
        } _tallRichHandsome;
    }
    @end
    
    @implementation MJPerson
    
    - (void)setTall:(BOOL)tall
    {
        if (tall) {
            _tallRichHandsome.bits |= MJTallMask;
        } else {
            _tallRichHandsome.bits &= ~MJTallMask;
        }
    }
    
    - (BOOL)isTall
    {
        return !!(_tallRichHandsome.bits & MJTallMask);
    }
    
    - (void)setRich:(BOOL)rich
    {
        if (rich) {
            _tallRichHandsome.bits |= MJRichMask;
        } else {
            _tallRichHandsome.bits &= ~MJRichMask;
        }
    }
    
    - (BOOL)isRich
    {
        return !!(_tallRichHandsome.bits & MJRichMask);
    }
    
    - (void)setHandsome:(BOOL)handsome
    {
        if (handsome) {
            _tallRichHandsome.bits |= MJHandsomeMask;
        } else {
            _tallRichHandsome.bits &= ~MJHandsomeMask;
        }
    }
    
    - (BOOL)isHandsome
    {
        return !!(_tallRichHandsome.bits & MJHandsomeMask);
    }
    
    
    
    - (void)setThin:(BOOL)thin
    {
        if (thin) {
            _tallRichHandsome.bits |= MJThinMask;
        } else {
            _tallRichHandsome.bits &= ~MJThinMask;
        }
    }
    
    - (BOOL)isThin
    {
        return !!(_tallRichHandsome.bits & MJThinMask);
    }
    
    @end
    

    isa详解--位域

    Class对象,Meta-Class对象最后三位地址值都是0

    二、class结构

    class_rw_t(可以更方便的区分分类跟类的信息)

    class_ro_t

    注:class_ro_t 存储类的基本信息 当有分类的时候 将当前的class_ro_t 数据跟分类的信息存储到class_rw_t中

    method_t
    Type Encoding
    方法缓存(其实就是通过isa指针查找类或者元类对象里面的cache_t的bucket_t里面是否缓存了此方法)
    散列表原理(通过key生成一个索引)
    • 散列表也叫做哈希表是根据关键码值(Key value)而直接进行访问的[数据结构],也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做[散列函数]

    1、如果是一个方法列表的话:方法名@selector(方法名)&_mask(也就是cache_t里面的mask_t)生成索引,其他位置都成NULL,牺牲内存空间换取执行效率


    注:不论@selector的值怎么变,&_mask以后的值都会小于或者等于_mask的值,所以mask_t 是散列表的长度 - 1

    2、如果是两个方法列表的话



    3、如果两个方法缓存的索引值是一样的话,会将当前索引-1进行存储,如果有值的话 继续-1
    取值的时候:先根据索引进行比较key是否是同一个key,如果是的话 直接取值,如果不是的话索引-1继续查找,如果索引为0的话 就去查找_mask 也就是数组的最后一个,重新继续查找
    一开始的mask 是有大小的 不是从0开始的


    注:哪一个对象调用了方法,就缓存到哪一个对象的cache里面
    如果超出容量 新的容量=旧的容量 * 2 然后会清空旧的缓存,只存储新的缓存


    相关文章

      网友评论

          本文标题:底层原理(五)------Class详解

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