2011-12-09 24 views
5

मेरे पास यह प्रश्न here (साथ ही एसओ पर अन्य quesrtions), और उद्देश्य-सी संग्रह और तेज़ गणना के बारे में ऐप्पल दस्तावेज़ है। अगर एक NSArray विभिन्न प्रकार के साथ आबादी वाले क्या स्पष्ट नहीं किया जाता है, और एक पाश की तरह बनाई गई है:विभिन्न प्रकार के एनएसएआरएआरई पर तेज गणना

for (NSString *string in myArray) 
    NSLog(@"%@\n", string); 

वास्तव में क्या यहाँ होता है? लूप किसी भी चीज पर छोड़ देगा जो NSString नहीं है? उदाहरण के लिए, यदि (तर्क के लिए) UIView सरणी में है, तो क्या होगा जब लूप उस आइटम से मुकाबला करेगा?

+3

तेजी से गणन वर्ग पर "अपने शब्द लेता है"। @awfullyjohn अज्ञात कक्षाओं के सदस्यों के साथ एक सरणी को संभालने का सबसे अच्छा समाधान प्रदान करता है। कोई अंतर्निहित फ़िल्टरिंग नहीं हो रही है और परिणामस्वरूप एक विधि को कॉल करने में परिणाम हो सकता है जो रिसीवर संभाल नहीं सकता ... क्रैश –

उत्तर

9

आप ऐसा क्यों करना चाहते हैं? मुझे लगता है कि बदबूदार और अनजान व्यवहार का कारण बन जाएगा। ,

for (id object in myArray) { 
    NSString *string = (NSString *)object; 
    NSLog(@"%@\n", string); 
} 

सिर्फ इसलिए कि आप डाली object(NSString *) के रूप में नहीं है

for (id object in myArray) { 
    // Check what kind of class it is 
    if ([object isKindOfClass:[UIView class]]) { 
     // Do something 
    } 
    else { 
     // Handle accordingly 
    } 
} 

क्या आप अपने उदाहरण में क्या कर रहे हैं के रूप में प्रभावी रूप से एक ही है: अपने सरणी विभिन्न तत्वों के साथ पॉपुलेटेड है, तो इस का प्रयोग मतलब string वास्तव में NSString ऑब्जेक्ट पर इंगित करेगा। इस तरह से NSLog() पर कॉल करने से विधि NSObject protocol के अनुसार विधि को कॉल करेगी, जिसे सरणी के अंदर संदर्भित किया जा रहा वर्ग हो सकता है या नहीं। अगर यह अनुरूप है, तो वह इसे प्रिंट करेगा। अन्यथा, यह दुर्घटनाग्रस्त हो जाएगा।

+1

एक अच्छा मुद्दा है, लेकिन यह सवाल का जवाब नहीं देता है। – PengOne

+0

सवाल वास्तव में ऐसा कुछ करने की तुलना में उद्देश्य-सी की गहरी समझ है। इसके अलावा, मैं हाल ही में सी # काम कर रहा हूं जहां संग्रह में जाने वाला प्रकार निर्दिष्ट किया जा सकता है। –

+1

सच है। मैं अपना जवाब अपडेट कर दूंगा, लेकिन मूल रूप से, आपने मुझे इसे हरा दिया। – john

2

दिलचस्प सवाल। तेजी से गणना के लिए सबसे सामान्य वाक्य रचना

for (NSObject *obj in myArray) 
    NSLog(@"%@\n", obj); 

मुझे विश्वास है कि बजाय

for (NSString *string in myArray) 
    NSLog(@"%@\n", string); 

करने से, आप बस प्रत्येक वस्तु एक NSString के रूप में कास्ट कर रहे हैं है। यही है, मेरा मानना ​​है कि इसके बाद के संस्करण

for (NSObject *obj in myArray) { 
    NSString *string = obj; 
    NSLog(@"%@\n", string); 
} 

के बराबर है मैं नहीं पा सके एप्पल के documentation for Fast Enumeration में इस बात का सटीक उल्लेख है, लेकिन आप एक उदाहरण पर यह जांच कर सकते हैं और देखो क्या होता।

+1

"सबसे सामान्य" संस्करण '(आईडी में ob obj) के लिए नहीं होगा (क्योंकि उस कवर (छोटी संख्या) के) वस्तुएं जो 'एनएसओब्जेक्ट' से नहीं उतरती हैं)? –

2

मैंने अभी एक त्वरित उदाहरण की कोशिश की है ... यह मेरा कोड है।

NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1]; 
NSNumber *number = [NSNumber numberWithInteger:6]; 
[array addObject:number]; 
[array addObject:@"Second"]; 

अब मैं बस वस्तु, कोई समस्या नहीं लॉग ऑन करता है, तो। NSNumber उदाहरण NSString के रूप में डाला जा रहा है, लेकिन दोनों विधियां -description पर प्रतिक्रिया देती हैं, इसलिए यह कोई समस्या नहीं है।

for (NSString *string in array) 
{ 
    NSLog(@"%@", string); 
} 

हालांकि, अगर मैं NSString पर -length लॉग ऑन करने का प्रयास ...

for (NSString *string in array) 
{ 
    NSLog(@"%i", string.length); 
} 

... फेंक देता है NSInvalidArgumentException क्योंकि एक NSNumber-length चयनकर्ता का जवाब नहीं है। लंबी कहानी छोटी, उद्देश्य-सी आपको बहुत सारी रस्सी देती है। अपने साथ लटकाओ मत।

+0

एनएसएनंबर को एनएसएसटींग के रूप में नहीं डाला जा रहा है। एनएसएनंबर और एनएसएसटींग दोनों एनएसओब्जेक्ट के वंशज हैं, जिनमें से एनएसएलओजी 'विवरण' कहता है, जैसा कि आप कहते हैं। लेकिन इसमें कोई कास्टिंग शामिल नहीं है। –

+0

ओह मैं देखता हूँ। मुझे लगता है कि मैं कोड-समापन सुविधाओं के साथ सिर्फ कास्टिंग उलझन में हूँ। जैसा कि मैं उदाहरण लिख रहा था, मुझे 'NSNumber' के उदाहरण पर' लम्बाई 'संदेश के बारे में कोई चेतावनी नहीं मिली। –

+0

आह! ठीक है ... मैं अब भी देख रहा हूं कि आपका क्या मतलब है। एनएसएनंबर को एनएसएसटींग के रूप में 'स्ट्रिंग' में डाला जा रहा है। मैंने सोचा था कि आप कह रहे थे कि एनएसएलओजी कास्टिंग कर रहा था ('विवरण' के उल्लेख से)। मेरी गलती! –

3

आपको यह समझना होगा कि obj-c में एक पॉइंटर में कोई प्रकार की जानकारी नहीं है। भले ही आप NSString* लिखते हैं, यह केवल एक संकलन जांच है। रनटाइम के दौरान, सब कुछ सिर्फ id है।

ओब्जे-सी रनटाइम कभी भी जांच नहीं करता है कि ऑब्जेक्ट दिए गए वर्ग के हैं या नहीं। आप NSNumbers को समस्याओं के बिना एनएसएसटींग पॉइंटर्स में डाल सकते हैं। एक त्रुटि तब दिखाई देती है जब आप किसी विधि को कॉल करने का प्रयास करते हैं (एक संदेश भेजें) जिसे ऑब्जेक्ट पर परिभाषित नहीं किया गया है।

तेजी से गणना कैसे काम करती है? यह बिल्कुल वैसा ही है:


for (NSUInteger i = 0; i < myArray.count; i++) { 
    NSString* string = [myArray objectAtIndex:i]; 

    [...] 
} 

यह तेज़ है क्योंकि यह निम्न स्तर पर चल रहा है।

1

isKindOfClass करने के लिए सभी NSObject के जवाब के बाद से, आप अभी भी कास्टिंग एक न्यूनतम करने के लिए रख सकता है:

for(NSString *string in myArray) { 
    if (![string isKindOfClass:[NSString class]]) 
     continue; 
    // proceed, knowing you have a valid NSString * 
    // ... 
} 
संबंधित मुद्दे