Déclaration et vérification / comparaison (énumération de bitmask) dans Objective-C

Vous savez dans Cocoa il y a cette chose, par exemple vous pouvez créer un UIView et faire:

 view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 

J’ai un UIView personnalisé avec plusieurs états, que j’ai défini dans un enum comme ceci:

 enum DownloadViewStatus { FileNotDownloaded, FileDownloading, FileDownloaded }; 

Pour chaque sous-vue créée, j’ai défini sa tag : subview1.tag = FileNotDownloaded;

Ensuite, j’ai un setter personnalisé pour l’état d’affichage qui effectue les opérations suivantes:

 for (UIView *subview in self.subviews) { if (subview.tag == viewStatus) subview.hidden = NO; else subview.hidden = YES; } 

Mais ce que j’essaie de faire , c’est de permettre ceci:

 subview1.tag = FileNotDownloaded | FileDownloaded; 

Donc, mon sous- subview1 apparaît dans deux états de ma vue. Actuellement, il ne figure dans aucun de ces deux états depuis le | l’opérateur semble append les deux valeurs enum.

Y-a-t-il un moyen de faire ça?

Déclaration de Bitmasks:

Alternativement, vous pouvez atsortingbuer des valeurs absolues ( 1 , 2 , 4 ,…) comme ceci:

 typedef enum : NSUInteger { FileNotDownloaded = (1 << 0), // => 00000001 FileDownloading = (1 << 1), // => 00000010 FileDownloaded = (1 << 2) // => 00000100 } DownloadViewStatus; 

ou en utilisant les macros modernes NS_OPTIONS / NS_ENUM :

 typedef NS_OPTIONS(NSUInteger, DownloadViewStatus) { FileNotDownloaded = (1 << 0), // => 00000001 FileDownloading = (1 << 1), // => 00000010 FileDownloaded = (1 << 2) // => 00000100 }; 

(voir la réponse d’ Abizern pour plus d’informations sur ce dernier)

Le concept de bitmasks consiste à (généralement) définir chaque valeur enum avec un seul bit défini.

Ainsi, deux valeurs OR effectuent les opérations suivantes:

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

ce qui équivaut à:

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

Comparaison des bitmasks:

Une chose à garder à l’esprit lors de la vérification contre les masques de bits:

Vérification de l’égalité exacte:

Supposons que le statut est initialisé comme ceci:

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

Si vous voulez vérifier si le status est égal à FileNotDownloaded , vous pouvez utiliser:

 BOOL equals = (status == FileNotDownloaded); // => false 

ce qui équivaut à:

  00000101 // (FileNotDownloaded | FileDownloaded) == 00000100 // FileDownloaded ----------- = 00000000 // false 

Vérification de “l’adhésion”:

Si vous voulez vérifier si le status contient simplement FileNotDownloaded , vous devez utiliser:

 BOOL contains = (status & FileNotDownloaded) != 0; // => true 00000101 // (FileNotDownloaded | FileDownloaded) & 00000100 // FileDownloaded ----------- = 00000100 // FileDownloaded != 00000000 // 0 ----------- = 00000001 // 1 => true 

Voir la différence subtile (et pourquoi votre expression “if” actuelle est probablement incorrecte)?

Alors que @Regexident a fourni une excellente réponse – je dois mentionner la manière moderne d’Objective-C de déclarer les options énumérées avec NS_OPTIONS :

 typedef NS_OPTIONS(NSUInteger, DownloadViewStatus) { FileNotDownloaded = 0, FileDownloading = 1 << 0, FileDownloaded = 1 << 1 }; 

Référence supplémentaire:

  • NSHipster
  • Je suis le morse
 enum DownloadViewStatus { FileNotDownloaded = 1, FileDownloading = 2, FileDowloaded = 4 }; 

Cela vous permettra d’exécuter efficacement des OR et des AND au niveau du bit.