一、位运算的补充
#import "ViewController.h"
//typedef enum {
// MJOptionsOne = 1, // 0b0001
// MJOptionsTwo = 2, // 0b0010
// MJOptionsThree = 4, // 0b0100
// MJOptionsFour = 8 // 0b1000
//} MJOptions;
typedef enum {
MJOptionsNone = 0, // 0b0000
MJOptionsOne = 1<<0, // 0b0001
MJOptionsTwo = 1<<1, // 0b0010
MJOptionsThree = 1<<2, // 0b0100
MJOptionsFour = 1<<3 // 0b1000
} MJOptions;
@interface ViewController ()
@end
@implementation ViewController
/*取值的时按位与&
0b0001
0b0010
0b1000
------
0b1011
&0b0100
-----------
0b0000
*/
- (void)setOptions:(MJOptions)options
{
if (options & MJOptionsOne) {
NSLog(@"包含了MJOptionsOne");
}
if (options & MJOptionsTwo) {
NSLog(@"包含了MJOptionsTwo");
}
if (options & MJOptionsThree) {
NSLog(@"包含了MJOptionsThree");
}
if (options & MJOptionsFour) {
NSLog(@"包含了MJOptionsFour");
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setOptions: MJOptionsOne | MJOptionsFour];
// [self setOptions: MJOptionsOne + MJOptionsTwo + MJOptionsFour];
// NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
}
@end
二、isa详解
- **验证uintptr_t weakly_referenced和 uintptr_t deallocating **
三、Class的结构
四、Type Encoding
五、方法缓存
原理:
- 1.实例对象调用对象方法时通过isa指针找到类对象。
- 2.在类对象如果找到就把该方法缓存到散列表中,用@selector(方法名)作为key,把函数的地址_imp跟key一一对应,然后缓存到散列表中,散列表底层数据结构是数组。
- 3.如果在类对象中找不到该方法,就通过superclass指针去父类的类对象中查找,把父类的方法缓存到子类的散列表中。
源码分析:
_mask就是索引,_mask是变化的,发现散列表长度不够用时,就自动扩充。
缓存:让_key&_mask算出索引,根据索引进行缓存,如果发现该索引下有bucket_t,就让索引-1,就继续遍历直到找到合适的索引进行缓存。
取值:原来和缓存一样。
-
取值:
-
散列表长度不够用时,就自动扩充长度为:旧的长度x2(删掉原来的散列表重新分配)
-
查看缓存
总结:
- 1、牺牲内存空间提高方法查找调用的效率。
- 2、函数的地址值&_mask的结果<=_mask值。
网友评论