我想学习位屏蔽。据我了解,这是将某种类型的二进制值存储到一个变量中的方法。

如果上述假设是正确的,我想我可以做这样的事情:

typedef NSUInteger Traits;

enum
{
    TraitsCharacterHonest       = 0,
    TraitsCharacterOptimistic   = 1,
    TraitsCharacterPolite       = 4,
    TraitsCharacterDevious      = 8,
    TraitsPhysicalTall          = 16,
    TraitsPhysicalBeautiful     = 32,
    TraitsPhysicalFat           = 64,
    TraitsPhysicalBigEyes       = 128,
    TraitsPhysicalRedHair       = 256,
};

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (strong, nonatomic) NSString  *name;
@property (assign, nonatomic) Traits    *traits;

@end

问题1 是,如何为一个人分配更多特征?

问题2 是,我是否必须对枚举项添加越来越多的数字,或者有没有办法表明这一点?

最终,我想实现以下目标:
Person *john = [[Person alloc] init];

//here code that assigns john three traits: TraitsCharacterHonest,
//TraitsCharacterOptimistic and TraitsPhysicalBeautiful.

如果我正确理解的话,

john.traits应该是100011.,从右边读取,每个代表该特定枚举值/特征的地方..0表示不具有该值,而1表示具有该值。

能否请您就语法提出建议并在需要时解释一个特定方面?

最佳答案

我建议更改一些内容:

  • 枚举值可以更改为左移一个。我认为,这使编写起来更容易一些。
  • 不需要将typedef定义为NSUInteger,可以直接使用typedef enum声明枚举类型。
  • 而且,正如其他人所提到的那样,您的属性不应该是指向Traits类型的指针。

  • 我的代码如下所示:
    typedef enum
    {
        TraitsCharacterHonest       = 1 << 0,
        TraitsCharacterOptimistic   = 1 << 1,
        TraitsCharacterPolite       = 1 << 2,
        TraitsCharacterDevious      = 1 << 3,
        TraitsPhysicalTall          = 1 << 4,
        TraitsPhysicalBeautiful     = 1 << 5,
        TraitsPhysicalFat           = 1 << 6,
        TraitsPhysicalBigEyes       = 1 << 7,
        TraitsPhysicalRedHair       = 1 << 8
    } Traits;
    
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    @property (strong, nonatomic) NSString  *name;
    @property (assign, nonatomic) Traits     traits;
    
    @end
    

    设置约翰的特征将如下所示:
    Person *john = [[Person alloc] init];
    
    john.traits = TraitsCharacterHonest | TraitsCharacterOptimistic | TraitsPhysicalBeautiful;
    

    但是,虽然位字段对于学习很有用,但是调试起来确实很麻烦。如果你想去打印
    现在,此角色的特征是,您必须编写如下代码:
    NSMutableString *result = [NSMutableString string];
    
    if (self.traits & TraitsCharacterHonest)
    {
        [result appendString: @"Honest, "];
    }
    if (self.traits & TraitsCharacterOptimistic)
    {
        [result appendString: @"Optimistic, "];
    }
    if (self.traits & TraitsCharacterPolite)
    {
        [result appendString: @"Polite, "];
    }
    // etc...
    

    此外,诸如删除特征之类的操作的语法令人困惑。您必须使用&和一个NOT-ed常量,
    // remove 'Tall' trait
    john.traits = john.traits & ~TraitsPhysicalTall
    

    如果可以(并且性能不是太大问题),我希望使用更高级别的功能。也许一个带有字符串常量的NSSet?例如
    __unused static NSString *TraitsCharacterHonest = @"TraitsCharacterHonest";
    __unused static NSString *TraitsCharacterOptimistic = @"TraitsCharacterOptimistic";
    __unused static NSString *TraitsCharacterPolite = @"TraitsCharacterPolite";
    // etc...
    
    @interface Person : NSObject
    
    @property (strong, nonatomic) NSString     *name;
    @property (assign, nonatomic) NSMutableSet *traits;
    
    @end
    

    然后,您可以执行以下操作:
    // adding
    [john.traits addObject: TraitsCharacterHonest];
    // checking
    [john.traits containsObject: TraitsCharacterHonest];
    // removing
    [john.traits removeObject: TraitsCharacterHonest];
    

    对我来说更有意义。此外,您可以直接使用来打印特征描述
    NSLog(@"John's traits: %@", john.traits);
    

    这样您将获得合理的输出。

    10-04 11:00