OC-Runtime-isa
2020-07-05 本文已影响0人
xiaoyouPrince
OC - Runtime -> isa
- Objective-C 是一门动态性比较强的语言跟C/C++有着很大的不同
- Objective-C 的动态特性是由 Runtime API 来支撑的
- Runtime API 提供的接口基本都是C语言提供的,源码由C/C++/汇编语言编写
isa 详解
- 想要学习 Runtime,必须要对其底层结构有一定的了解,比如isa指针
- 在 arm64 架构之前,isa 就是一个普通的指针,存储着 Class、Meta-Class对象的内存地址
- 在 arm-64 架构之后,对isa 进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息。从源码中可以看到此架构下 isa 要 & 一个掩码才能获取到其Class 和meta-class 的内存地址
使用位域的好处
可以节约很多内存。
比如 BOOL 类型的变量,其在内存中占用 1个字节,但是其实际使用只有 1个比特。
底层开发中可以使用比特来保存较小的数据量。一个字节可以保存8个布尔量。
这样的操作需要使用按位操作符,实际效率会更高。
自己处理bool值
缺点:各位意义不是很清晰,扩展之后更加容易增加混乱程度。
// 保存bool的变量,后三位分别为高富帅
static BOOL bools = 0b00000000;
// 掩码
#define Height_mask (1<<0) // 最右边位 - height
#define Rich_mask (1<<1) // 最右边二位 - rich
#define Hansom_mask (1<<2) // 最右边三位 - hansome
#pragma mark - 取值
- (BOOL)height
{
return !!(bools & Height_mask);
}
- (BOOL)rich{
return !!(bools & Rich_mask);
}
- (BOOL)hansome{
return !!(bools & Hansom_mask);
}
#pragma mark - 赋值
-(void)setHeight:(BOOL)height{
if (height) {
bools |= Height_mask;
}else
{
bools &= ~Height_mask;
}
}
- (void)setRich:(BOOL)rich{
if (rich) {
bools |= Rich_mask;
}else
{
bools &= ~Rich_mask;
}
}
- (void)setHansome:(BOOL)hansome{
if (hansome) {
bools |= Hansom_mask;
}else
{
bools &= ~Hansom_mask;
}
}
使用结构体内建的位域技术
直接通过位域,可以直接访问结构体内部的,但是有些东西可能就不直观了。
struct values {
char height : 1; // 从低到高占据的位数
char rich: 1;
char hansom: 1;
} heightRichHandsom;
#pragma mark - 取值
- (BOOL)height
{
return !!heightRichHandsom.height;
}
- (BOOL)rich{
return !!heightRichHandsom.rich;
}
- (BOOL)hansome{
return !!heightRichHandsom.hansome;
}
#pragma mark - 赋值
-(void)setHeight:(BOOL)height{
heightRichHandsom.height = height;
}
- (void)setRich:(BOOL)rich{
heightRichHandsom.rich = rich;
}
- (void)setHansome:(BOOL)hansome{
heightRichHandsom.hansome = hansome;
}
共用体方式
系统方式是使用共用体,看起来更加清晰,扩展性也比较好
{
union{
// 真正使用的字节,
char bits;
struct {
char height : 1; // 具体的字节描述,更加清晰
char rich: 1;
char hansom: 1;
};
}heightRichHandsom;
}
// 掩码
#define Height_mask (1<<0) // 最右边位 - height
#define Rich_mask (1<<1) // 最右边二位 - rich
#define Hansom_mask (1<<2) // 最右边三位 - hansome
#pragma mark - 取值
- (BOOL)height
{
return !!(heightRichHandsom.bits & Height_mask);
}
- (BOOL)rich{
return !!(heightRichHandsom.bits & Rich_mask);
}
- (BOOL)hansome{
return !!(heightRichHandsom.bits & Hansom_mask);
}
#pragma mark - 赋值
-(void)setHeight:(BOOL)height{
if (height) {
heightRichHandsom.bits |= Height_mask;
}else
{
heightRichHandsom.bits &= ~Height_mask;
}
}
- (void)setRich:(BOOL)rich{
if (rich) {
heightRichHandsom.bits |= Rich_mask;
}else
{
heightRichHandsom.bits &= ~Rich_mask;
}
}
- (void)setHansome:(BOOL)hansome{
if (hansome) {
heightRichHandsom.bits |= Hansom_mask;
}else
{
heightRichHandsom.bits &= ~Hansom_mask;
}
}
枚举类型的设计
通常我们设计枚举有两种类型:可叠加
和 不可叠加
可叠加类型
此类如设置推送消息类型的,几种类型可以相互同时设置。
typedef NS_OPTIONS(NSUInteger, UIUserNotificationType) {
UIUserNotificationTypeNone = 0,
UIUserNotificationTypeBadge = 1 << 0,
UIUserNotificationTypeSound = 1 << 1,
UIUserNotificationTypeAlert = 1 << 2,
}
// 此类可以在 set方法中通过 if 判断具体包含哪一项
if (options & UIUserNotificationTypeNone){
// 设置的为 none 相关于关闭了
}
if (options & UIUserNotificationTypeBadge){
// 设置的为 横幅
}
if (options & UIUserNotificationTypeSound){
// 设置的为 声音
}
if (options & UIUserNotificationTypeAlert){
// 设置的为 alert
}
不可叠加类型
每种类型都是独立的,无需满足既是A又是B的情况,如下:
enum {
AUTO_HEAP_HOLES_SHRINKING = 1, // total size of holes is approaching zero
AUTO_HEAP_HOLES_EXHAUSTED = 2, // all holes exhausted, will use hitherto unused memory in "subzone"
AUTO_HEAP_SUBZONE_EXHAUSTED = 3, // will add subzone
AUTO_HEAP_REGION_EXHAUSTED = 4, // no more subzones available, need to add region
AUTO_HEAP_ARENA_EXHAUSTED = 5, // arena exhausted. (64-bit only)
};
// 内部判断也是比较简单,直接 if-else 处理即可
-- end