क्या मुझे NSNotFound से NSInteger या NSUInteger की तुलना करनी चाहिए? - आईओएस, उद्देश्य-सी

यहां मेरा कोड है:

NSArray *allIds = [self.purchasableObjects valueForKey:@"productIdentifier"];
NSInteger index = [allIds indexOfObject:productId];

if (index == NSNotFound)
return;

किस से तुलना करनी है NSNotFound... NSInteger या NSUInteger और क्यों?

उत्तर:

उत्तर № 1 के लिए 1

आपको उपयोग करना चाहिए NSUInteger

इसके पीछे का कारण है "ऐरे इंडेक्स माइनस में नहीं जा रहा है (इंडेक्स -5 पर ऑब्जेक्ट)"

typedef int NSInteger;
typedef unsigned int NSUInteger;

NSInteger का उपयोग तब किया जाना चाहिए जब प्लस या माइनस में मान प्राप्त करने की संभावना हो।

आशा करता हूँ की ये काम करेगा। धन्यवाद


जवाब के लिए 2 № 2

कारण है कि वह इस सवाल पूछा है क्योंकि AppKit फाउंडेशन इंडेक्स के साथ असंगत है, विशेष रूप से के लिए NSMenu तथा NSTableView:

id obj = ...;
NSMenu * menu = ...;

/* This returns an NSInteger, returning -1 (which when casted, is NSNotFound) */
NSInteger index = [ menu indexOfItemWithRepresentedObject:obj ];

/* This returns an NSUInteger, since arrays cannot have negative indices. */
NSUInteger idx = [ [ menu itemArray ] indexOfObjectIdenticalTo:obj ];

इस वजह से, किसी को आगे और पीछे करना होगा, लेकिन इससे नई समस्याएं पैदा होती हैं:

क्योंकि अनुक्रमणिका ऋणात्मक नहीं हो सकती, पंक्तियों की संख्या (या सबमेनस) आदि) सामान्य सरणियों के HALF द्वारा कम किया जा सकता है।

यदि आप एक वस्तु को पढ़ने या सम्मिलित करने का प्रयास करते हैंएक यूआई तत्व में नकारात्मक सूचकांक (-2), आपको सीमा अपवाद नहीं मिलता है। यदि आप अहस्ताक्षरित हैं, तो सूचकांक अपरिभाषित है। तो यह कोड, जो गलत है, त्रुटि के बिना संकलित करता है:

id obj = ...;
NSMenu * menu = ...;
/* Or the result of some integer arithmetic. */
NSInteger idx = -2;

/* Compiles, doesn"t throw exception. Index COULD be NSIntegerMax - 1, but the ending index is undefined. */
[ menu insertItem:obj atIndex:idx ];

/* Compiles, but throws NSRangeException. */
[ [ menu mutableArrayValueForKey:@"items" ] insertObject:obj atIndex:( NSUInteger )idx ];

पहले मामले में, जब एक आइटम डालते हैं परे menu.numberOfItems (जो एक है NSInteger), सामान्य तौर पर (लेकिन गारंटी नहीं), विधि के बराबर है [ menu addItem ]। इसलिए, सूचकांक इस प्रकार बदल दिया गया है:

[ menu insertItem:obj atIndex:MIN( idx, menu.numberOfItems ) ];

लेकिन AppKit के पुराने संस्करणों में, सूचकांक गोल है!

[ menu insertItem:obj atIndex:MAX( MIN( idx, menu.numberOfItems ), 0 ) ];

यूआई तत्वों से अनुक्रमित सम्मिलित करने और / या प्राप्त करते समय एक प्रोग्रामर को बहुत ध्यान रखना चाहिए, या एक का उपयोग करना चाहिए NSArrayController बजाय।

सभी मामलों के लिए, हालांकि यह है दोनों की जाँच करना सुरक्षित है [ menu indexOfItem:obj ] तथा [ array indexOfObjectIdenticalTo:obj ] कर रहे हैं बराबरी का NSNotFound, इसलिए जब तक आप एक स्पष्ट कलाकारों का उपयोग करते हैं। जबकि NSNotFound का घोषित प्रकार है NSUInteger, यह है परिभाषित जैसा NSUIntegerMax, जो जब डाली जाती है -1 के बराबर होती है। कभी नहीँ मान से कम होने पर जाँच करें NSNotFound जैसा कि आप अभी तक एक और अनंत लूप बनाएंगे। लेकिन बेझिझक:

NSInteger index = [ menu indexOfItem:nonexistantObject ];
if( ( NSUInteger )index == NSNotFound ) {
...blah...
}

या

NSUInteger index = [ array indexOfItem:nonexistantObject ];
if( index == NSNotFound ) {
...blah...
}

हालाँकि, यदि रिटर्न प्रकार है NSInteger, तुम्हे करना चाहिए नहीं मान लें कि यदि लौटा हुआ सूचकांक isn "t NSNotFound यह एक वैध सूचकांक है (विशेषकर यदि आप "3-पार्टी फ्रेमवर्क या लाइब्रेरी का उपयोग कर रहे हैं)। इसके बजाय, आपको यह देखने के लिए जांचना चाहिए कि लौटा हुआ सूचकांक वैध सीमा में है या नहीं:

NSInteger index = [ menu indexOfItem:nonexistantObject ];
if( ( NSUInteger )index == NSNotFound ) {
/* Can"t find it, so insert or do something else. */
} else if( !( index >= 0 && index <= menu.numberOfItems ) ) {
/* Throw an invalid range exception. There"s a major bug! */
} else {
/* woo hoo! we found it! */
}

निश्चित रूप से यह जांच अनिवार्य रूप से महंगी है, इसलिए इसका उपयोग केवल ऐसे कोड में किया जाना चाहिए जो अक्सर चलते हैं नहीं एक लूप में, या डिबग कोड में। यदि आप यह सुनिश्चित करना चाहते हैं कि आपको हमेशा जल्द से जल्द एक वैध सूचकांक मिले, तो आपको ब्लॉक एन्यूमरेशन का उपयोग करना चाहिए, जो कि किसी भी अन्य विधि के मुकाबले तेज है

id obj = ..;
/* Get an array from the UI, or just use a normal array. */
NSArray * array = [ menu itemArray ];

/* Find an index quickly */
NSUInteger index = [ array indexOfObjectWithOptions:NSEnumerationConcurrent passingTest:^BOOL( NSUInteger idx, id testObj, BOOL * stop ) {
if( obj == testObj ) {
*stop = TRUE;
return TRUE;
}
} ];

लौटाया गया सूचकांक है गारंटी वैध होने के लिए, या तो NSNotFound या अंदर NSMakeRange( 0, array.count - 1 )। सूचना मैंने उपयोग नहीं की -isEqual: जैसा कि मैं एक विशिष्ट के लिए जाँच कर रहा था उदाहरण ऐसी वस्तु नहीं जिसे व्याख्यायित किया जा सके समान दूसरे के रूप में।

यदि आपको लूप में सूचकांकों के साथ कुछ करने की आवश्यकता है, तो आप एक ही तकनीक का उपयोग कर सकते हैं (ध्यान दें कि सूचकांक ब्लॉक में पारित हो गए हैं, और हैं हमेशा वैध):

[ array enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^( NSUInteger idx, id obj, BOOL * stop ) {
/* do something to this object, like adding it to another array, etc */
} ];

सरणियों पर ब्लॉक विधियों का उपयोग करना हमेशा आपको मान्य सूचक मिलते हैं, जिन्हें कास्ट किया जा सकता है NSIntegers UI तत्वों में उपयोग के लिए। रेंज-विशिष्ट ब्लॉक विधियां भी हैं जो मूल्यों को आगे भी प्रतिबंधित कर सकती हैं। मैं पढ़ने की सलाह देता हूं NSArray तथा NSMutableArray संकेत के लिए प्रलेखन। कोड को जोड़कर ब्लॉक का दुरुपयोग करना भी काफी आसान है [enumerate...withBlock:][3] विधियाँ, खासकर यदि आप वस्तुओं को दूसरे संग्रह वर्ग में जोड़ रहे हैं:

NSArray * source = ...;
NSMutableArray * dest = ...;

[ source enumerateObjectsUsingBlock:^( NSUInteger idx, id obj, BOOL * stop ) {
if( /* some test */ ) {
/* This is wasteful, and possibly incorrect if you"re using NSEnumerationConcurrent */
[ dest addObject:obj ];
}
} ];

इसके बजाय ऐसा करना बेहतर है:

/* block removed for clarity */
NSArray * source = ...;
NSMutableArray * dest = ...;
NSIndexSet * indices = [ source indexesOfObjectsPassingTest:testBlock ];

[ dest addObjects:[ source objectsAtIndexes:indices ]  ];

लंबे समय से घुमावदार प्रतिक्रिया के लिए खेद है, लेकिन यह कोको इंडेक्सिंग (और विशेष रूप से) के साथ एक समस्या है NSNotFound) कि मेरे डेवलपर्स को हल करना और फिर से हल करना है, इसलिए मैंने सोचा कि यह साझा करने के लिए उपयोगी होगा।


संबंधित सवाल
सबसे लोकप्रिय