需求:设计一个对象DXPerson,三个BOOL类型属性(tall,rich,handsom),只占用一个字节内存

// 0b代表二进制
0b 0000 0001

0b 1111 1111 == 十进制255

按位与(&)运算,作用:可以取出特定的位,设置特定位的值为0

// 都是1才是1,否则就是0
 0011
&1111
------
 0011
 
 // 取出特定的位值,假设取 0011 倒数第二位值,使其倒数第二位1,其它值为0,进行&运算
  0011
 &0010
 ------
  0010
  
// 可以设置特定位的值为0,其它保持不变,比如倒数第二位
  0011
 &1101
 ------
  0001

按位或(|)运算,作用:可以设置特定位的值为1

// 只要有1都是1
 0011
|1011
------
 1011

// 设置特定位的值为1,其它位保持不变,比如第一位
 0011
|1010
------
 1011

mask: 掩码,一般用来按位与(&)运算

.h文件声明

@interface DXPerson : NSObject

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

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

@end

.m文件实现

#import "DXPerson.h"

@interface DXPerson(){
    char _tallRichHandsome;
}

@end

//mask: 掩码,一般用来按位与(&)运算
#define DXTallMask (1<<0)
#define DXRichMask (1<<1)
#define DXHandsomeMask (1<<2)

@implementation DXPerson

- (instancetype)init{
    self = [super init];
    if (self) {
        // 初始值设置 tall == 1 rich == 0 handsome == 1
        _tallRichHandsome = 0b00000101;
    }
    return self;
}

- (BOOL)isTall{
    // 强制转换成BOOL类型
    return !!(_tallRichHandsome & DXTallMask);
}
- (BOOL)isRich{
    // 强制转换成BOOL类型,否则打印出来2
    return !!(_tallRichHandsome & DXRichMask);
}

- (BOOL)isHandsome{
    // 强制转换成BOOL类型,否则打印出来4
    return !!(_tallRichHandsome & DXHandsomeMask);
}

- (void)setTall:(BOOL)tall{
    if (tall) {
       // _tallRichHandsome = _tallRichHandsome | DXTallMask;
        _tallRichHandsome |= DXTallMask;
    } else {
       // _tallRichHandsome = _tallRichHandsome & ~DXTallMask;
        _tallRichHandsome &= ~DXTallMask;
    }
}
- (void)setRich:(BOOL)rich{
    if (rich) {
        // _tallRichHandsome = (_tallRichHandsome | DXTallMask);
        _tallRichHandsome |= DXRichMask;
    } else {
        // _tallRichHandsome = (_tallRichHandsome & ~DXTallMask);
        _tallRichHandsome &= ~DXRichMask;
    }
}
- (void)setHandsome:(BOOL)handsome{
    if (handsome) {
        // _tallRichHandsome = _tallRichHandsome | DXTallMask;
        _tallRichHandsome |= DXHandsomeMask;
    } else {
         _tallRichHandsome = (_tallRichHandsome & ~DXTallMask);
        _tallRichHandsome &= ~DXHandsomeMask;
    }
}
@end

其中

#define DXTallMask (1<<0)
#define DXRichMask (1<<1)
#define DXHandsomeMask (1<<2)

等价于

#define DXTallMask 0b00000001
#define DXRichMask 0b00000010
#define DXHandsomeMask 0b00000100

等价于

#define DXTallMask 1
#define DXRichMask 2
#define DXHandsomeMask 4

在Objective-C中,经常看到左移运算,目的就是为了使用二进制设置值,取值,使用了一个字节,保存了多个属性,大大节省了内存占用

示例:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

get方法,本质就是取特定位的值,tall取最后一位值,rich取倒数第二位值,handsome取倒数第三位值

set方法设值,本质就是设置特定位的值,tall设置最后一位值,rich设置倒数第二位值,handsome设置倒数第三位值