Runtime
1 – OC的动态性是由 Runtime API来支撑的, Runtime API提供的接口基本上是 C语言的,源码是由 C、C++、汇编所编写的
2 – 要想学习 Runtime,首先要先了解它的一些底层数据结构,比如 isa指针、union
union
1 – arm64架构之前,isa就是一普通指针,存储了 Class、Meta-Class对象的内存地址;而 arm64之后就把 isa优成了共同体结构,使用位域来存储更多的信息
2 – 为什么使用共用体优化 isa
① 未使用共用体之前
1 #import <Foundation/Foundation.h>
2 #import <objc/runtime.h>
3 @interface Person : NSObject
4
5 // Person中有三个属性:高富帅
6 @property (assign, nonatomic, getter = isTall) BOOL tall;
7 @property (assign, nonatomic, getter = isRich) BOOL rich;
8 @property (assign, nonatomic, getter = isHansome) BOOL handsome;
9
10 @end
11
12 @implementation Person
13
14 @end
15
16 int main(int argc, const char * argv[]) {
17 @autoreleasepool {
18
19 Person *person = [[Person alloc] init];
20 person.rich = YES;
21 person.tall = NO;
22 person.handsome = NO;
23
24 NSLog(@"tall:%d rich:%d hansome:%d", person.isTall, person.isRich, person.isHansome);
25
26 // 内存大小
27 NSLog(@"%zd", class_getInstanceSize([Person class]));// 16
28 // 3个 BOOL属性共占 3字节;内部的 isa占 8字节;总计 11字节
29 // 内存对其,输出 16
30
31 }
32 return 0;
33 }
② 使用共用体:一个字节就可以对 Person的高、富、帅 3个信息进行存储
1 #import <Foundation/Foundation.h>
2 #import <objc/runtime.h>
3
4 // 掩码一般同按位与 &搭配使用
5 // 注意细节:建议掩码使用小括号括起来,方便运算、阅读
6 #define TallMask (1<<0) // 0b 0000 0001
7 #define RichMask (1<<1) // 0b 0000 0010
8 #define HandsomeMask (1<<2) // 0b 0000 0100
9
10 @interface Person : NSObject{
11
12 // 使用一个字节就可以包含高、富、帅三者的信息
13 char _TRH;// tallRichHansome
14 }
15
16 // 高富帅
17 @property (assign, nonatomic, getter = isTall) BOOL tall;
18 @property (assign, nonatomic, getter = isRich) BOOL rich;
19 @property (assign, nonatomic, getter = isHansome) BOOL handsome;
20
21 @end
22
23 @implementation Person
24
25 // 初始值我们约定:tall = YES; rich = YES; handsome = NO;
26 - (instancetype)init{
27
28 if (self = [super init]) {
29
30 _TRH = 0b00000011; // 高、富、不帅
31 }
32 return self;
33 }
34
35 // 赋值比较绕,我们先把取值搞定
36 // getter:利用位与运算可取出对应位的值即可
37 - (BOOL)isTall{
38
39 // 使用两个 !完成 强制 BOOL转换的功能
40
41 return !!(_TRH & TallMask);// 同 return (BOOL)(_TRH & TallMask);
42 }
43
44 - (BOOL)isRich{
45
46 return !!(_TRH & RichMask);
47 }
48
49 - (BOOL)isHansome{
50 return (BOOL)(_TRH & HandsomeMask);
51 }
52
53
54 // setter
55 - (void)setTall:(BOOL)tall{
56
57
58 if (tall) {
59 _TRH |= TallMask;// 如果是 YES,使用位或
60 } else {
61
62 // 如果是 NO:先按位取反然后后再进行位与运算
63 _TRH &= ~TallMask;
64
65 // ~0001 == 1110
66 // 1110 & 0011 == 0010
67 }
68 }
69
70 - (void)setRich:(BOOL)rich{
71 if (rich) {
72 _TRH |= RichMask;
73 } else {
74 _TRH &= ~RichMask;
75 }
76 }
77
78 - (void)setHandsome:(BOOL)handsome{
79
80 if (handsome) {
81
82 _TRH |= HandsomeMask;
83 // 0011 | 0100 == 0111
84
85 NSLog(@"%d",HandsomeMask);
86 } else {
87 _TRH &= ~HandsomeMask;
88 }
89 }
90
91 @end
92
93 int main(int argc, const char * argv[]) {
94 @autoreleasepool {
95
96 Person *person = [[Person alloc] init];
97 NSLog(@"tall:%d rich:%d hansome:%d", person.isTall, person.isRich, person.isHansome);
98 // tall:1 rich:1 hansome:0
99
100 //赋值后
101 person.tall = NO;
102 person.rich = NO;
103 person.handsome = NO;
104 NSLog(@"tall:%d rich:%d hansome:%d", person.isTall, person.isRich, person.isHansome);
105 // tall:0 rich:0 hansome:0
106 }
107 return 0;
108 }
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/271598.html