Objective C でのビットマスク 質問する

Objective C でのビットマスク 質問する

ビット マスキングについて学びたいです。私の理解では、これは特定のタイプのバイナリ値を 1 つの変数に格納することを意味します。

上記の仮定が正しい場合、次のようなことができると考えました。

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問題は、1 人の人物に複数の特性を割り当てるにはどうすればよいかということです。

質問2つまり、列挙項目に常に増加する数字を入力する必要がありますか、それともこれを示す方法がありますか?

最終的に私は次のようなことを達成したいと思っています。

Person *john = [[Person alloc] init];

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

私の理解が正しければ、

john.traits は 100011 である必要があります。右から読み取ると、各位置は特定の列挙値 / 特性を表します。0 はそれがないことを意味し、1 はそれがあることを意味します。

必要に応じて、構文に関するアドバイスや特定の側面について説明していただけますか?

ベストアンサー1

いくつかの点を変更することをお勧めします:

  • 列挙値は、1 を左にシフトしたものに変更できます。私の意見では、記述が少し簡単になります。

  • NSUInteger に typedef する必要はなく、 を使用して enum 型を直接宣言できます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

John の特性を設定すると次のようになります。

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&定数を使用する必要があります。

// 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);

適切な出力が得られます。

おすすめ記事