उद्घोषणा और जाँच / तुलना (बिटमास्क-) उद्देश्य-सी में enums


79

आप कोको में जानते हैं कि यह बात है, उदाहरण के लिए आप एक 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से दो राज्यों में मेरा प्रदर्शन होता है। वर्तमान में, यह उन दो राज्यों में से किसी में नहीं दिखता है क्योंकि |ऑपरेटर को दो एनम मूल्यों को जोड़ना प्रतीत होता है।

क्या ऐसा करने के लिए कोई रास्ता है?


आपका (subview.tag == viewStatus)मुझे गलत लगता है। ((subview.tag & viewStatus) != 0x0)तब तक होना चाहिए , जब तक कि आप केवल सटीक मिलान के लिए जाँच न करें। जिस स्थिति में आपको पहले स्थान पर बिटमास्क की आवश्यकता नहीं होगी, लेकिन सिर्फ एक पुराना पुराना एनम। मेरे उत्तर का दूसरा भाग देखें।
रेगेक्सिडेंट

जवाबों:


279

घोषणा करने वाले बिटमास्क:

वैकल्पिक रूप से निरपेक्ष मान निर्दिष्ट करने के लिए ( 1, 2, 4, ...) आप घोषणा कर सकते हैं bitmasks (इन कैसे कहा जाता है) इस तरह:

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

या आधुनिक ObjC NS_OPTIONS/ NS_ENUMmacros का उपयोग कर :

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

( उत्तरार्द्ध पर अधिक जानकारी के लिए अबिज़र्न का जवाब देखें )

बिटकॉइम्स की अवधारणा (आमतौर पर) एक बिट सेट के साथ प्रत्येक एनम वैल्यू को परिभाषित करना है।

इसलिए 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

सूक्ष्म अंतर देखें (और क्यों आपका वर्तमान "यदि" -प्रोटेक्शन शायद गलत है)?


@ धन्यवाद: धन्यवाद! यह प्रश्न पहले से प्रदान की गई तुलना में थोड़ा अधिक स्पष्टीकरण के योग्य था।
रेगेक्सिडेंट

हाँ, लेकिन आप द्विआधारी मान को हेक्साडेसिमल मान (0x से पहले) के रूप में स्वरूपित कर रहे हैं। बिटमास्क बिट स्तर पर काम करते हैं। सरल गलती, मुझे यकीन है कि आपने इसे नोटिस भी नहीं किया था। लेकिन कोई व्यक्ति इसे देख सकता है और गलत तरीके से मान सकता है कि आपके पास प्रति वर्ष अधिकतम 8 विकल्प हो सकते हैं, जब आपके पास वास्तव में अधिकतम 32 अलग-अलग विकल्प हो सकते हैं। सुधार: FileNotDownloaded = (0x1 << 0), // => %...00000001आदि
माइकल ज़िम्मरमैन

1
Apple एनम और बिट मास्क घोषणाओं के लिए मैक्रोज़ NS_ENUM और NS_OPTION की एक अद्भुत जोड़ी प्रदान करता है। उन्हें इस्तेमाल करें। कुछ अच्छे विवरणों के लिए NSHipster साइट देखें।
uchuugaka

2
पूरी तरह से उनके बारे में पता है। ;) (अबीज़र्न का जवाब देखें) वैसे भी, NS_OPTIONSपूर्णता की खातिर एक बदलाव जोड़ा गया है ।
रेगेक्सिडेंट

1
सही। मैं देख रहा हूं कि आपके पास ओवरफ्लो का क्या मतलब है। शायद यह बस ((स्थिति और FileNotDownloaded) == FileNotDownloaded) होना चाहिए, इसलिए केवल कुछ ही परिणाम संभव हैं।
uchuugaka

20

जबकि @Regexident ने एक उत्कृष्ट उत्तर प्रदान किया है - मुझे Enumerer विकल्प की घोषणा करने के आधुनिक उद्देश्य-सी तरीके का उल्लेख करना चाहिए NS_OPTIONS:

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

आगे का संदर्भ:


हां NS_ENUM और NS_OPTION मैक्रोज़ कमाल के हैं।
uchuugaka

1
enum DownloadViewStatus {
  FileNotDownloaded = 1,
  FileDownloading = 2,
  FileDowloaded = 4
};

यह आपको बिटवाइज़ और AND का प्रभावी प्रदर्शन करने देगा।


4
मान परिभाषित करने के मानक तरीका है 1 << 0, 1 << 1, 1 << 2आदि यह स्पष्ट आप बिट और मास्क के साथ काम कर रहे हैं बनाता है।
माइक वेलर

1
@AhmedAlHafoudh: लेख हालांकि ओपी की दूसरी समस्या को संबोधित नहीं करता है: बिटमास्क के साथ काम करना (बनाम बस उन्हें घोषित करना)। मेरा जवाब देखिए।
रेगेक्सिडेंट

1

उपयोगी फ़ंक्शन आप पठनीयता में सुधार के लिए बिटमास्क जाँच के लिए उपयोग कर सकते हैं।

BOOL bitmaskContains(NSUInteger bitmask, NSUInteger contains) {
    return (bitmask & contains) != 0;
}

अधिक सख्त (bitmask & contains) == contains- यह शून्य के साथ भी काम करेगाcontains
डीजेएम 00 एनएन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.