10-Runtime-02

一、位运算的补充

#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值。

你可能感兴趣的:(10-Runtime-02)