iOS - Runtime

OC的消息机制

OC是一门动态性比较强的编程语言,允许很多操作推迟到程序运行时再进行
OC的动态性就是由Runtime来支撑和实现的,Runtime是一套C语言的API,封装了很多动态性相关的函数
平时编写的OC代码,底层都是转成Runtime API进行调用

OC中的方法调用其实是转成objc_msgSend函数的调用,给receiver(方法调用者)发送一条消息(selector方法名)
objc_msgSend底层有3大阶段

1.消息发送(当前类、父类中查找)

在这里插入图片描述

2.动态方法解析

在这里插入图片描述

3.消息转发

在这里插入图片描述

Runtime作用

利用关联对象(AssociatedObject)给分类添加属性
遍历类的所有成员变量(修改textfield的占位文字颜色、字典转模型、自动归档解档)
交换方法实现
利用消息转发机制解决方法找不到的异常问题

isa详解

> nonpointer
	0:代表普通的指针,存储着Class、Meta-Class对象的内存地址
	1:代表优化过,使用位域存储更多的信息
>has_assoc
	是否有设置过关联对象,如果没有,释放时会更快
>has_cxx_dtor
	是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
>shiftcls
	存储着Class、Meta-Class对象的内存地址信息
>magic
	用于在调试时分辩对象是否未完成初始化
>weakly_referenced
	是否有被弱引用指向过,如果没有,释放时会更快
>deallocating
	对象是否正在释放
>extra_rc
	里面存储的值是引用计数器减一
>has_sidetable_rc
	引用计数器是否过大无法存储在isa中
	如果为1,那么引用计数会存储在一个叫SideTable的类的属性中

class_rw_t

class_rw_t里面的methods、properties、protocols是二维数组,是可读可写的,包含类的初始类容,分类的内容

struct method_t{
	SEL name; //函数名
	const char *types; //编码(返回值类型,参数类型)
	IMP imp; //指向函数的指针(函数地址)
}
>IMP代表函数的具体实现
	typedef id _Nullable (*IMP)id _Nullable, SEL _Nonnull,...);
>SEL代表方法/函数名,一般叫做选择器,底层结构跟char *类似
	1.可以通过@selector()和sel_registerName()获得
	2.可以通过sel_getName()和NSStringFromSelector()转成字符串
	3.不同类中相同名字的方法,所对应的选择器是相同的
	typedef struct objc_selector *SEL;
	
struct class_rw_t{
	method_array_t methods;  // -> methods:method_list_t数组  method_list_t:method_t数组
 	property_array_t properties;
	protocol_array_t protocols;
}

cache_t

Class内部结构中有个方法缓存(cache_t),用==散列表(哈希表)==来缓存曾经调用过的方法,可以提高方法查找速度

struct bucket_t{
	cache_key_t _key; // SEL作为key
	IMP _imp; //函数地址
}
struct method_t{
	struct bucket_t *_buckets; //散列表
	mask_t _mask;//散列表长度-1
	mask_t _occupied;//已经缓存的方法数量
}
//缓存查找
bucket_t *cache_t::find(cache_key_t k, id receiver)

Super本质

super调用,底层会转换为objc_msgSendSuper2函数的调用,接收2个参数「struct objc_super2、SEL」
struct objc_super2 {
    id receiver; //消息接受者
    Class current_class;//receiver的Class对象
};

/**
 [super message]的底层实现
 1.消息接受者仍然是子类对象
 2.从父类开始查找方法的实现
 */

struct objc_super {
    __unsafe_unretained _Nonnull id receiver; //消息接受者
    __unsafe_unretained _Nonnull Class super_class;// 消息接收者父类
};

- (void)run
{
    //super 调用的receiver仍然是当前类对象
    [super run];
}

类似于isa存储的位域使用

掩码,一般用来按位与(&)运算的
//#define CJTallMask 1
//#define CJRichMask 2
//#define CJHandsomeMask 4
//
//#define CJTallMask 0b00000001
//#define CJRichMask 0b00000010
//#define CJHandsomeMask 0b0000100

#define CJTallMask 1<<0
#define CJRichMask 1<<1
#define CJHandsomeMask 1<<2

union Date {
    int year;
    int month;
    int day;
};

@interface CJPerson ()
{
//    char _tallRichHandsome;//0b 0000 0000
    
    //位域
    struct{
        char tall : 1;
        char rich : 1;
        char handsome : 1;
    } _tallRichHandsome;
    
//    //联合体(可读性高)
//    union {
//        char bits;//0b 0000 0000
//        //位域
//        struct{
//            char tall : 1;
//            char rich : 1;
//            char handsome : 1;
//        };
//    } _tallRichHandsome;//实例对象
}
@end

@implementation CJPerson

- (instancetype)init
{
    self = [super init];
    if (self) {
//        _tallRichHandsome = 0b00000000;
        
    }
    return self;
}

- (void)setIsRich:(BOOL)isRich
{
    if (isRich) {
        _tallRichHandsome.rich = _tallRichHandsome.rich|CJRichMask;
    }else{
        _tallRichHandsome.rich = _tallRichHandsome.rich&(~(CJRichMask));
    }
}

- (BOOL)isRich{
    return _tallRichHandsome.rich&CJRichMask;
}
@end

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值