iOS底层系列之<14>--Runtime(二)方法

1、Class的结构

/*
struct objc_class {
    Class isa;
    Class superclass;
    cache_t cache; //方法缓存
    class_data_bits_t bits; // 用于获取具体的类信息 (位域技术---&FAST_DATA_MASK---> struct class_rw_t)
};

struct class_rw_t {
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro; // (指向------> struct class_ro_t)
    method_list_t *methods; // 方法列表
    property_list_t *properties; // 属性列表
    const protocol_list_t *protocols; // 协议列表
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
};

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize; // instance 对象占用的空间
#ifdef __LP64__
    uint32_t reserved;
#endif
    const uint8_t *ivarLayout;
    const char *name;  // 类名
    method_list_t *baseMethodList;
    protocol_list_t *baseProtocols;
    const ivar_list_t * ivars; // 成员变量列表
    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
}
*/
  • class_rw_t里面的methods、properties、protocols实际上是二维数组,是可读可写的,包含了类的初始内容、分类的内容

在这里插入图片描述

  • class_ro_t里面的baseMethodList、baseProtocols、ivars、baseProperties是一维数组,是只读的,包含了类的初始内容
    在这里插入图片描述

2、Type Encoding

  • iOS中,提供了一个叫@encode的指令,可以将具体的类型表示成字符串编码
    在这里插入图片描述

在这里插入图片描述

NSLog(@“SEL->%s\nvoid->%s”,@encode(SEL),@encode(void));
打印结果:
SEL->:
void->v

3、方法缓存

struct objc_class {
    Class isa;
    Class superclass;
    cache_t cache; //方法缓存
    class_data_bits_t bits; // 用于获取具体的类信息 (位域技术---&FAST_DATA_MASK---> struct class_rw_t)
};

struct class_rw_t {
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro; // (指向------> struct class_ro_t)
    method_list_t *methods; // 方法列表
    property_list_t *properties; // 属性列表
    const protocol_list_t *protocols; // 协议列表
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
};

第一次会到 <method_list_t *methods; // 方法列表> 里面去寻找
如果这里面没找到,会到父类里面取寻找
如果父类没寻找到,会到基类里面寻找
其中只要一旦找到了,就会放在<cache_t cache; //方法缓存> 里面
下次再调用这个方法,就不用再很麻烦地去寻找这个方法了

struct cache_t {
	struct bucket_t *_buckets; // 散列表
	mask_t _mask; // 散列表的长度 -1 
	mask_t _occupied; // 已经缓存的方法数量
}

struct bucket_t {
	cache_key_t _key; // SEL 作为key
	IMP _imp; // 函数的内存地址
}

// 调用方法之前,先来这个缓存里面查看,是否有过缓存,如果有,就直接通过缓存找到函数地址,去调用函数,这样效率就会很高了

4、散列缓存的原理

  • 下面这个图应该能表达清楚了
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值