1. ホーム
  2. objective-c

Objective-Cの(bitmask)enumの宣言とチェック/比較

2023-07-07 02:26:23

質問

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 つの enum 値を追加するようです。

そのような方法はあるのでしょうか?

どのように解決するのですか?

Bitmasksを宣言する。

絶対値を割り当てる代わりに ( 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の回答 をご覧ください。)

ビットマスクのコンセプトは、(通常) 各 enum 値を 1 つのビットセットで定義することです。

したがって OR を2つの値にすると、次のようになります。

DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101

と等価である。

  00000001 // FileNotDownloaded
| 00000100 // FileDownloaded
----------
= 00000101 // (FileNotDownloaded | FileDownloaded)

Bitmaskを比較する。

ビットマスクの照合で気をつけるべきことが一つあります。

完全に等しいかどうかをチェックすること。

ステータスがこのように初期化されているとします。

DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101

を確認したい場合は status イコール FileNotDownloaded を、使用することができます。

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"- 式がおそらく間違っている理由も)?