Runtime(一)、位域

296 阅读1分钟

要想学习Runtime,首先要了解它底层的一些常用数据结构,比如isa指针

在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的内存地址

从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息

共用体与位域

demo:

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        
        MJPerson *person = [[MJPerson alloc] init];
        person.thin = YES;
        person.rich = YES;
        person.handsome = NO;
        
        NSLog(@"thin:%d rich:%d hansome:%d", person.isThin, person.isRich, person.isHandsome);
    }
    return 0;
}

MJPerson.h

@interface MJPerson : NSObject

- (void)setTall:(BOOL)tall;
- (void)setRich:(BOOL)rich;
- (void)setHandsome:(BOOL)handsome;
- (void)setThin:(BOOL)thin;

- (BOOL)isTall;
- (BOOL)isRich;
- (BOOL)isHandsome;
- (BOOL)isThin;

@end

MJPersion.m

@interface MJPerson()
{
    union {
        int bits;
        
        struct {
            char tall : 1;
            char rich : 1;
            char handsome : 1;
            char thin : 1;
        };
    } _tallRichHandsome;
}
@end

#define MJTallMask (1<<0)
#define MJRichMask (1<<1)
#define MJHandsomeMask (1<<2)
#define MJThinMask (1<<3)

@implementation MJPerson

- (void)setTall:(BOOL)tall
{
    if (tall) {
        _tallRichHandsome.bits |= MJTallMask;
    } else {
        _tallRichHandsome.bits &= ~MJTallMask;
    }
}

- (BOOL)isTall
{
    return !!(_tallRichHandsome.bits & MJTallMask);
}

- (void)setRich:(BOOL)rich
{
    if (rich) {
        _tallRichHandsome.bits |= MJRichMask;
    } else {
        _tallRichHandsome.bits &= ~MJRichMask;
    }
}

- (BOOL)isRich
{
    return !!(_tallRichHandsome.bits & MJRichMask);
}

- (void)setHandsome:(BOOL)handsome
{
    if (handsome) {
        _tallRichHandsome.bits |= MJHandsomeMask;
    } else {
        _tallRichHandsome.bits &= ~MJHandsomeMask;
    }
}

- (BOOL)isHandsome
{
    return !!(_tallRichHandsome.bits & MJHandsomeMask);
}



- (void)setThin:(BOOL)thin
{
    if (thin) {
        _tallRichHandsome.bits |= MJThinMask;
    } else {
        _tallRichHandsome.bits &= ~MJThinMask;
    }
}

- (BOOL)isThin
{
    return !!(_tallRichHandsome.bits & MJThinMask);
}

@end
  • 共用体成员共用一块内存地址。
  • 位域仅仅起到一个提示信息的作用。去掉也没有影响。

1. 小Tips方便理解

位与: 任何与0相与都是0,得到0 任何与1相与都是本身,不变

位或: 任何与1相或都是1,得到1 任何与0相或都是本身,不变

    if(yes){
        1.想控制的位得到1 --> 或上1
        2.其他位不变 --> 或上0
     }else{   
        1.想控制的位得到0 --> 与上 0
        2.其他位不变 ---> 与上1
     }

2.如果是4位,掩码就要变

union {
        int bits;
        
        struct {
            char tall : 4;
            char rich : 4;
            char handsome : 4;
            char thin : 4;
        };
 } _tallRichHandsome;
    
#define MJTallMask (1<<0)
#define MJRichMask (1<<4)
#define MJHandsomeMask (1<<8)
#define MJThinMask (1<<12)

枚举中的位运算

 (void)viewDidLoad {
    [super viewDidLoad];
        
    [self setOptions: MJOptionsOne | MJOptionsFour];
    [self setOptions: MJOptionsOne + MJOptionsTwo + MJOptionsFour];
    
//    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin;
//
//    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
//
//    [self addObserver:self forKeyPath:@"age" options:options context:NULL];
}
typedef enum {
//    MJOptionsNone = 0,    // 0b0000
    MJOptionsOne = 1<<0,   // 0b0001
    MJOptionsTwo = 1<<1,   // 0b0010
    MJOptionsThree = 1<<2, // 0b0100
    MJOptionsFour = 1<<3   // 0b1000
} MJOptions;


/*
 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");
    }
}