Ответ 1
Объявление битовых масок:
Альтернативно для назначения абсолютных значений (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 для получения дополнительной информации о последних)
Понятие битмаски состоит в том, чтобы (обычно) определять каждое значение перечисления с помощью одного набора бит.
Следовательно, OR
ввод двух значений делает следующее:
DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101
что эквивалентно:
00000001 // FileNotDownloaded
| 00000100 // FileDownloaded
----------
= 00000101 // (FileNotDownloaded | FileDownloaded)
Сравнение битмаск:
Одна вещь, которую нужно иметь в виду при проверке битмакса:
Проверка точного равенства:
Предположим, что статус инициализирован следующим образом:
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
См. тонкую разницу (и почему ваше текущее "если" -выражение, вероятно, неверно)?