巧用位移枚举

博客介绍了枚举的多种用法,包括位移枚举用法、枚举赋值,还提及枚举位运算新写法,用一个枚举值表示三个字段且各字段有 YES 和 NO 状态。此外,介绍了用结构体 + 位域、共用体 + 位域重新实现相关功能,以及枚举标示数组下标和长度、一个枚举值标示两个多状态字段的新写法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 位移枚举的用法

// - 定义 NSLayoutAttributeLeft  NSLayoutAttributeRight  是系统定义,分别为 1, 2, 3, 这个写法很秀...大家注意
typedef NS_OPTIONS(NSInteger, MASAttribute) {
    MASAttributeLeft = 1 << NSLayoutAttributeLeft,
    MASAttributeRight = 1 << NSLayoutAttributeRight,
    MASAttributeTop = 1 << NSLayoutAttributeTop,
 }
    
// - 使用 1. 适合 同时存在 MASAttributeLeft | MASAttributeRight |  MASAttributeTop
    if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left];
    if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right];
    if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top];
    
//- 使用 2.  适合只存在 MASAttributeLeft 或者  MASAttributeRight 或者 MASAttributeTop 中的某一种情况
	switch (attrs & 0xFF) {
        case MASAttributeLeft:
            break;
        case MASAttributeRight:
            break;
        case MASAttributeTop:
            break;
        default:
            break;
    }

2. 枚举赋值

/** 表示两个 BOOL 值 */
typedef NS_OPTIONS(NSInteger, DYRoomStateType) {
    DYRoomStateTypeUnknow               = 0,
    DYRoomStateTypeFirstConnect         = 1 << 1,
    DYRoomStateTypeFirstEnterRoom       = 1 << 2,
    DYRoomStateTypeFirstQuitRoom       = 1 << 3,
	DYRoomStateTypeFirstTestRoom       = 1 << 4,
};

static inline void setCurrentTypeToTypeStaute(NSInteger* currentType, NSInteger toType, BOOL status){
	// - 加入这个type 已知当前是  1001 , 加入的是 0010, 结果是1011;
    if (status) {
        (*currentType) = (*currentType) | (toType);
    }else{
    	// - 移除这个type 已知当前是  1011 , 移除的是 0010, 结果是1001;
        (*currentType) = (*currentType) & (~toType);
    }
}

// - 获取是不是包含这个 type 已知当前是  1011 , 测试的是 0010, 结果是0010;
static inline BOOL getCurrentTypeIsType(NSInteger* currentType, NSInteger isType){
    return ((*currentType) & isType) == isType;
}

2. 枚举位运算的新写法(一个枚举值标表示三个字段 每个字段有 YES 和 NO 两个状态) 这里的!! 是 int 类型转成 BOOL类型的思路不错

// - 使用位运算赋值
typedef NS_OPTIONS(NSInteger, QGMask) {
    QGMaskHandsome = 1 << 0,
    QGMaskRich = 1 << 1,
    QGMaskTall = 1 << 2,
 }

@interface MJPerson : NSObject

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

- (BOOL)isTall;
- (BOOL)isRich;
- (BOOL)isHandsome;
@interface MJPerson(){
	char  _tallRichHandsome;
}

@end

@implementation MJPerson
- (instancetype)init{
    self = [super init];
    if (self) {
    	_tallRichHandsome = 0b00000000;
    }
    return self;
}
- (void)setTall:(BOOL)tall{
	if(tall){
		_tallRichHandsome |= QGMaskTall;
	}else{
		_tallRichHandsome &= ~QGMaskTall;
	}
}

- (BOOL)isTall{
    return !!(_tallRichHandsome & QGMaskTall) ;
}

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

- (BOOL)isRich{
    return !!(_tallRichHandsome & QGMaskRich) ;
}

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

- (BOOL)isHandsome{
    return  !!(_tallRichHandsome & QGMaskHandsome) ;
}

3. 结构体+位域 (使用结构体+位域重新实现上述的功能)

    
@interface MJPerson : NSObject
struct {
        char tall : 2;
        char rich : 2;
        char handsome : 2;
    }_tallRichHandsome;
@end

@implementation MJPerson
- (void)setTall:(BOOL)tall
{
    _tallRichHandsome.tall = tall;
}
- (void)setRich:(BOOL)rich
{
    _tallRichHandsome.rich = rich;
}
- (void)setHandsome:(BOOL)handsome
{
    _tallRichHandsome.handsome = handsome;
}
- (BOOL)tall
{
    return _tallRichHandsome.tall;
}
- (BOOL)rich
{
    return _tallRichHandsome.rich;
}
- (BOOL)handsome
{
    return _tallRichHandsome.handsome;
}
@end

4. 共用体+位域 (使用共用体+位域重新实现上述的功能)

#define TallMask (1<<2) // 0b00000100 4
#define RichMask (1<<1) // 0b00000010 2
#define HandsomeMask (1<<0) // 0b00000001 1

@interface Person()
{
    union {
        char bits;
       // 结构体仅仅是为了增强代码可读性,无实质用处 只是用来标识 bits中的后三位对应着的内容表示的是什么
        struct {
            char tall : 2;
            char rich : 2;
            char handsome : 2;
        };
    }_tallRichHandsome;
}
@end

@implementation Person

- (void)setTall:(BOOL)tall{
// - 下边两个方法的写法都可以, 第一个可以增强可读性, 第二个提高效率
// - _tallRichHandsome.tall = tall;

    if (tall) {
        _tallRichHandsome.bits |= TallMask;
    }else{
        _tallRichHandsome.bits &= ~TallMask;
    }
}
- (void)setRich:(BOOL)rich{
    if (rich) {
        _tallRichHandsome.bits |= RichMask;
    }else{
        _tallRichHandsome.bits &= ~RichMask;
    }
}
- (void)setHandsome:(BOOL)handsome{
    if (handsome) {
        _tallRichHandsome.bits |= HandsomeMask;
    }else{
        _tallRichHandsome.bits &= ~HandsomeMask;
    }
}
- (BOOL)tall{
// - 下边两个方法的写法都可以, 第一个可以增强可读性, 第二个提高效率
// - return _tallRichHandsome.tall;
    return !!(_tallRichHandsome.bits & TallMask);
}
- (BOOL)rich{
    return !!(_tallRichHandsome.bits & RichMask);
}
- (BOOL)handsome{
    return !!(_tallRichHandsome.bits & HandsomeMask);
}

5. 枚举的新写法 (用枚举标示数组下标和数组长度)

/** 连麦的人物的角色 */
typedef NS_ENUM(NSUInteger, QIEOnlineMatchPeopleRole) {
    QIEOnlineMatchPeopleRoleHost = 0, /**< 连麦时候不显示画面的 */
    QIEOnlineMatchPeopleRoleConvener = 1, /**< 连麦时候需要显示画面的 */
    QIEOnlineMatchUsersArrayLenght = 2, /**< 用户数组的长度 */
};

/** 用户数组 0 : 主播数组, 1: 选手数组 */
- (NSMutableArray<NSMutableArray *> *)usersArray{
    if(!_usersArray){
        _usersArray = [NSMutableArray array];
        NSMutableArray <AgoraLiveTranscodingUser *> *hostArray = [NSMutableArray array];
        NSMutableArray <AgoraLiveTranscodingUser *>  *guestArray = [NSMutableArray array];
        [_usersArray addObject:hostArray];
        [_usersArray addObject:guestArray];
    }
    return _usersArray;
}

// - 根据枚举取出对应下标的元素
[[self.usersArray objectAtIndex:QIEOnlineMatchPeopleRoleHost] addObject:user];
[[self.usersArray objectAtIndex:QIEOnlineMatchPeopleRoleConvener] addObject:user];
[[self.usersArray objectAtIndex:QIEOnlineMatchPeopleRoleConvener] addObject:user];

// - 根据枚举 判断数组长度是不是达到了最大值
if(self.usersArray.count == QIEOnlineMatchUsersArrayLenght){
	NSLog(@"数组长度已经达到最大值");
}

5. 枚举的新写法 (用一个枚举值标示两个字段, 每个字段有多个状态)

/** 推流器的枚举
    第一个低八表示 pk 模式 (个人赛和线上赛)
    第二个低八位标示 推流方式(声网推流或者斗鱼推流)
 */
typedef NS_ENUM(NSInteger,  QIEPushFlowType) {
    
    /** 使用用于个人连麦或者线上赛 */
    QIEPushFlowTypeForMask = 0x00FF,
    QIEPushFlowForOnlineMatch = 1,
    QIEPushFlowForPersonal = 2,
    QIEPushFlowTypeForSet = (QIEPushFlowForOnlineMatch | QIEPushFlowForPersonal),
    
    /** 使用斗鱼的推流器或者声网推流器 */
    QIEPushFlowTypeByMask = 0xFF00,
    QIEPushFlowByDy = 256,
    QIEPushFlowByAgora = 512,
    QIEPushFlowTypeBySet = (QIEPushFlowByDy | QIEPushFlowByAgora)
};

// - setter 方法
- (void)setPushFlowType:(QIEPushFlowType)pushFlowType{
	// - 验证参数合法性
    NSAssert((pushFlowType & QIEPushFlowTypeForMask) != QIEPushFlowTypeForSet), @"QIEPushFlowFor之间不能做位运算...");
    NSAssert((pushFlowType & QIEPushFlowTypeByMask) != QIEPushFlowTypeBySet, @"QIEPushFlowBy之间不能做位运算...");
    
    // - 赋值
    if((pushFlowType & QIEPushFlowTypeForMask) & QIEPushFlowTypeForSet){
        // - 说明 QIEPushFlowTypeFor 是   QIEPushFlowTypeForSet 的其中之一,也就是说 第一低八位不是 0
        _pushFlowType = (pushFlowType & QIEPushFlowTypeForMask) + (_pushFlowType & QIEPushFlowTypeByMask);
    }
    if((pushFlowType & QIEPushFlowTypeByMask) & QIEPushFlowTypeBySet){
        // - 说明 QIEPushFlowTypeBy 是   QIEPushFlowTypeBySet 的其中之一,也就是说 第二低八位不是 0
        _pushFlowType = (_pushFlowType & QIEPushFlowTypeForMask) + (pushFlowType & QIEPushFlowTypeByMask);
    }
}

NSTest *t = [[NSTest alloc]init];
// - 会崩溃, 停在断言的位置
t.pushFlowType = QIEPushFlowForPersonal | QIEPushFlowForOnlineMatch; 和  t.pushFlowType = QIEPushFlowByDy | QIEPushFlowByAgora;

// - 可以记录值  QIEPushFlowByAgora 和  QIEPushFlowForOnlineMatch
t.pushFlowType =QIEPushFlowByAgora | QIEPushFlowForOnlineMatch;

// - 切换不会使原有的值丢失 (QIEPushFlowForOnlineMatch 还会保留)
t.pushFlowType =QIEPushFlowByDy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值