Cocoaにはこのことがあることを知っています。たとえば、UIView
を作成して次のことができます。
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
次のようにUIView
で定義した複数の状態を持つカスタムenum
があります。
enum DownloadViewStatus {
FileNotDownloaded,
FileDownloading,
FileDownloaded
};
作成されたサブビューごとに、tag
:subview1.tag = FileNotDownloaded;
を設定します
次に、私は次のことを行うビューステート用のカスタムセッターを持っています:
for (UIView *subview in self.subviews) {
if (subview.tag == viewStatus)
subview.hidden = NO;
else
subview.hidden = YES;
}
しかし、私がやろうとしていること、これを許可することです:
subview1.tag = FileNotDownloaded | FileDownloaded;
したがって、私のsubview1
は、ビューの2つの状態で表示されます。現在、|
演算子は2つの列挙値を追加しているように見えるため、これらの2つの状態のいずれにも表示されません。
それを行う方法はありますか?
絶対値(1
、2
、4
、…)次のように宣言できますビットマスク(これらの呼び出し方法):
typedef enum : NSUInteger {
FileNotDownloaded = (1 << 0), // => 00000001
FileDownloading = (1 << 1), // => 00000010
FileDownloaded = (1 << 2) // => 00000100
} DownloadViewStatus;
または、最新のObjCのNS_OPTIONS
/NS_ENUM
マクロ:
typedef NS_OPTIONS(NSUInteger, DownloadViewStatus) {
FileNotDownloaded = (1 << 0), // => 00000001
FileDownloading = (1 << 1), // => 00000010
FileDownloaded = (1 << 2) // => 00000100
};
(後者の詳細については Abizernの答え を参照)
ビットマスクの概念は、(通常)単一のビットセットで各列挙値を定義することです。
したがって、2つの値をOR
ingすると次のことが行われます。
DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101
次と同等です:
00000001 // FileNotDownloaded
| 00000100 // FileDownloaded
----------
= 00000101 // (FileNotDownloaded | FileDownloaded)
ビットマスクをチェックする際に留意すべきこと:
ステータスが次のように初期化されると仮定しましょう:
DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101
status
equalsFileNotDownloaded
かどうかを確認したい場合は、次を使用できます。
BOOL equals = (status == FileNotDownloaded); // => false
次と同等です:
00000101 // (FileNotDownloaded | FileDownloaded)
== 00000100 // FileDownloaded
-----------
= 00000000 // false
status
が単にに含まれるFileNotDownloaded
を含むかどうかを確認する場合は、以下を使用する必要があります。
BOOL contains = (status & FileNotDownloaded) != 0; // => true
00000101 // (FileNotDownloaded | FileDownloaded)
& 00000100 // FileDownloaded
-----------
= 00000100 // FileDownloaded
!= 00000000 // 0
-----------
= 00000001 // 1 => true
微妙な違いをご覧ください(そして、なぜ現在の「if」式がおそらく間違っているのでしょうか)?
@Regexidentは素晴らしい答えを提供してくれましたが、NS_OPTIONS
:
typedef NS_OPTIONS(NSUInteger, DownloadViewStatus) {
FileNotDownloaded = 0,
FileDownloading = 1 << 0,
FileDownloaded = 1 << 1
};
詳細なリファレンス:
読みやすくするためにビットマスクチェックに使用できる便利な関数。
BOOL bitmaskContains(NSUInteger bitmask, NSUInteger contains) {
return (bitmask & contains) != 0;
}
enum DownloadViewStatus {
FileNotDownloaded = 1,
FileDownloading = 2,
FileDowloaded = 4
};
これにより、ビット単位のORとANDを効果的に実行できます。