美文网首页
底层原理(五)------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详解

    Objective-C是一门动态性比较强的编程语言,跟C、C++等语言有着很大的不同Objective-C的动态性...

  • iOS底层原理探索—内存管理(一)

    探索底层原理,积累从点滴做起 往期回顾 iOS底层原理探索 — OC对象的本质 iOS底层原理探索 — class...

  • 建立你自己的iOS开发知识体系

    目录: 底层相关 iOS底层原理总结 - 探寻Class的本质iOS底层原理总结篇-- 探寻OC对象的本质iOS底...

  • 100篇技术文章

    1.Class类的底层实现原理 - 链接 链接 2.Category分类的底层实现原理 - 链接 3.Block块...

  • Runloop

    Runloop 实现原理及应用iOS - RunLoop 底层源码详解及具体运用

  • 底层-Class详解(iOS)

    iOS的开发语言objective-c,它的真实面目是它不是真正的面向对象语言,而抽象理解为此而已。其实它就是C+...

  • 底层原理

    iOS底层原理总结 - Category的本质 KVO详解及底层实现青少年一定要读的KVO指南 iOS 底层解析w...

  • 热修复

    Android 热修复方案选型 1.原理部分 1.1class&dex文件详解 什么是class文件?能够被 JV...

  • iOS底层探索 --- Runtime(三)Category底层

    本文章参考自:iOS 开发:『Runtime』详解(三)Category 底层原理[https://www.jia...

  • 2019-03-02

    Runtime Objective-C Runtime iOS底层原理探究-Runtime isa 和 Class...

网友评论

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

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