2009-09-29 15 views
107

मैं अभी भी उद्देश्य-सी के लिए नया हूं और मैं सोच रहा हूं कि निम्नलिखित दो कथनों के बीच क्या अंतर है?का उपयोग -परफॉर्म चयनकर्ता: बनाम बस विधि को कॉल करना

[object performSelector:@selector(doSomething)]; 

[object doSomething]; 

उत्तर

183

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

इस प्रकार इन बराबर हैं भले ही:

[anObject aMethod]; 
[anObject performSelector:@selector(aMethod)]; 

दूसरा रूप आपको ऐसा करने की अनुमति देता है:

SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation(); 
[anObject performSelector: aSelector]; 

इससे पहले कि आप संदेश भेजें।

+3

यह उनका कहना है कि आप वास्तव में findTheAppropriateSelectorForTheCurrentSituation() aSelector करने का परिणाम आवंटित होगा लायक है, तो आह्वान [anObject performSelector: aSelector]। @ चयनकर्ता एक एसईएल पैदा करता है। –

+4

'प्रदर्शन चयनकर्ता' का उपयोग करना, ऐसा कुछ है जो आप संभवतः केवल तभी करते हैं जब आप अपनी कक्षा में लक्ष्य-क्रिया लागू करते हैं। भाई बहन 'प्रदर्शन चयनकर्ता बैकग्राउंड: ऑब्जेक्ट के साथ:' और 'प्रदर्शन चयनकर्ताऑनमेन थ्रेड: ऑब्जेक्ट: प्रतीक्षा करें नहीं:' अक्सर अधिक उपयोगी होते हैं। पृष्ठभूमि धागे को बढ़ाने के लिए, और बैक परिणाम को पृष्ठभूमि थ्रेड से मुख्य धागे पर कॉल करने के लिए। – PeyloW

+1

'प्रदर्शन चयनकर्ता' संकलन चेतावनियों को दबाने के लिए भी उपयोगी है। यदि आपको पता है कि विधि मौजूद है (जैसे 'respondsToSelector' का उपयोग करने के बाद), यह एक्सकोड को यह कहने से रोक देगा "हो सकता है कि आपका' चयनकर्ता 'का जवाब न दे। चेतावनी के वास्तविक कारण को जानने के लिए बस इसे _instead_ का उपयोग न करें।;) – Marc

11

@ennuikiller स्थान पर है। असल में, गतिशील रूप से जेनरेट किए गए चयनकर्ता उपयोगी होते हैं जब आप कोड को संकलित करते समय कॉल करने वाले विधि के नाम को नहीं जानते (और आमतौर पर संभवतः नहीं) कर सकते हैं।

एक महत्वपूर्ण अंतर यह है कि -performSelector: और दोस्तों (multi-threaded and delayed variants समेत) कुछ हद तक सीमित हैं कि वे 0-2 पैरामीटर के साथ विधियों के उपयोग के लिए डिज़ाइन किए गए हैं। उदाहरण के लिए, 0 पैरामीटर के साथ -outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation: पर कॉल करना और NSString को वापस करना बेहद कमजोर है, और प्रदान की गई विधियों द्वारा समर्थित नहीं है।

+4

ऐसा करने के लिए, आपको एक 'एनएसआईएनवोकेशन' ऑब्जेक्ट का उपयोग करना होगा। –

+6

एक और अंतर: 'प्रदर्शन चयनकर्ता:' और दोस्तों सभी ऑब्जेक्ट तर्क लेते हैं, जिसका अर्थ है कि आप उन्हें कॉल करने के लिए उपयोग नहीं कर सकते हैं (उदाहरण के लिए) 'setAlphaValue:', क्योंकि इसकी तर्क एक फ्लोट है। – Chuck

+0

दोनों उत्कृष्ट अंक हैं। –

3

चयनकर्ता अन्य भाषाओं में फ़ंक्शन पॉइंटर्स की तरह थोड़ा सा हैं। जब आप संकलित समय पर नहीं जानते हैं तो आप उन रन का उपयोग करते हैं जिन्हें आप रनटाइम पर कॉल करना चाहते हैं। साथ ही, फ़ंक्शन पॉइंटर्स की तरह, वे केवल आमंत्रण के क्रिया भाग को समाहित करते हैं। यदि विधि में पैरामीटर हैं, तो आपको उन्हें भी पास करना होगा।

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

+5

चयनकर्ता वास्तव में एक फ़ंक्शन पॉइंटर की तरह नहीं हैं जिसमें फ़ंक्शन पॉइंटर कुछ ऐसा है जो आप तर्कों के साथ कॉल कर सकते हैं और चयनकर्ता का उपयोग किसी भी ऑब्जेक्ट पर किसी विशेष विधि को कॉल करने के लिए किया जा सकता है; एक चयनकर्ता के पास फ़ंक्शन पॉइंटर जैसे आमंत्रण का पूर्ण संदर्भ नहीं होता है। – bbum

+1

चयनकर्ता फ़ंक्शन पॉइंटर्स के समान नहीं हैं, लेकिन मुझे अभी भी लगता है कि वे समान हैं। वे क्रियाओं का प्रतिनिधित्व करते हैं। सी फंक्शन पॉइंटर्स क्रियाओं का भी प्रतिनिधित्व करते हैं। अतिरिक्त संदर्भ के बिना भी उपयोगी नहीं है। चयनकर्ताओं को एक वस्तु और पैरामीटर की आवश्यकता होती है; फ़ंक्शन पॉइंटर्स को पैरामीटर की आवश्यकता होती है (जिसमें एक ऑब्जेक्ट शामिल हो सकता है जिस पर काम करना है)। मेरा मुद्दा यह था कि वे एनएसआईएनवोकेशन ऑब्जेक्ट्स से अलग कैसे हैं, जिसमें सभी आवश्यक संदर्भ शामिल हैं। शायद मेरी तुलना उलझन में थी, इस मामले में मैं क्षमा चाहता हूं। –

+1

चयनकर्ता फ़ंक्शन पॉइंटर्स नहीं हैं। आस - पास भी नहीं। वे वास्तविकता में सरल सी स्ट्रिंग्स हैं, जिनमें एक विधि का "नाम" होता है (जैसा कि 'फ़ंक्शन' के विपरीत होता है)। वे विधि हस्ताक्षर भी नहीं हैं, क्योंकि वे पैरामीटर के प्रकार एम्बेड नहीं करते हैं। एक ऑब्जेक्ट में एक ही चयनकर्ता (विभिन्न पैरा प्रकार, या अलग-अलग रिटर्न प्रकार) के लिए एक से अधिक विधि हो सकती हैं। –

-6

दोनों के बीच एक और सूक्ष्म अंतर है।

[object doSomething]; // is executed right away 

    [object performSelector:@selector(doSomething)]; // gets executed at the next runloop 

यहाँ से एप्पल प्रलेखन अंश है

"performSelector: withObject: afterDelay: वर्तमान धागे पर निर्दिष्ट चयनकर्ता अगले रन पाश चक्र के दौरान और एक वैकल्पिक देरी की अवधि के बाद अच्छा प्रदर्शन करता क्योंकि यह। चयनकर्ता को निष्पादित करने के लिए अगले रन लूप चक्र तक प्रतीक्षा करता है, ये विधियां वर्तमान में निष्पादित कोड से स्वचालित मिनी देरी प्रदान करती हैं। एकाधिक पंक्तिबद्ध चयनकर्ताओं को कतारबद्ध क्रम में एक के बाद एक किया जाता है। "

+1

आपका उत्तर वास्तव में गलत है। आपके द्वारा उद्धृत दस्तावेज़ 'प्रदर्शनकर्ता के बारे में है: ऑब्जेक्ट: बाद में:', लेकिन प्रश्न और आपका स्निपेट ['प्रदर्शन चयनकर्ता: '] (http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ का उपयोग कर रहे हैं फाउंडेशन/प्रोटोकॉल/एनएसओब्जेक्ट_Protocol/संदर्भ/NSObject.html # // apple_ref/doc/uid/20000052-BBCBGHFG), जो एक पूरी तरह से अलग विधि है। इसके लिए दस्तावेज़ों से: 'प्रदर्शन चयनकर्ता:' विधि रिसीवर को सीधे 'एक चयनकर्ता' संदेश भेजने के बराबर है। स्पष्टीकरण के लिए

+2

धन्यवाद जोश धन्यवाद। तुम सही हो; मैंने सोचा कि 'प्रदर्शन चयनकर्ता/प्रदर्शन चयनकर्ता: ऑब्जेक्ट/प्रदर्शन चयनकर्ता के साथ: ऑब्जेक्ट: बाद में डेले' सभी ने वैसे ही व्यवहार किया जो एक गलती थी। – avi

+0

अरे एवी। कोई भी मौका आप इस जवाब को हटा सकते हैं? आप सहमत हैं कि यह एक शॉकर है;) – robinCTS

10

प्रश्न में यह बहुत ही बुनियादी उदाहरण के लिए,

[object doSomething]; 
[object performSelector:@selector(doSomething)]; 

वहाँ क्या होने जा रहा है में कोई अंतर नहीं है। कुछ वस्तु द्वारा समकालिक रूप से निष्पादित किया जाएगा। केवल "doSomething" एक बहुत ही सरल विधि है, जो कुछ भी वापस नहीं करती है, और किसी भी पैरामीटर की आवश्यकता नहीं होती है।

यह थे कुछ थोड़ा और अधिक जटिल है, जैसे:

(void)doSomethingWithMyAge:(NSUInteger)age; 

बातें, जटिल हो जाएगा क्योंकि [वस्तु doSomethingWithMyAge: 42];

अब "प्रदर्शन चयनकर्ता" के किसी भी संस्करण के साथ नहीं कहा जा सकता है, क्योंकि पैरामीटर वाले सभी प्रकार केवल ऑब्जेक्ट पैरामीटर स्वीकार करते हैं।

चयनकर्ता यहाँ होगा "doSomethingWithMyAge:" लेकिन

[object performSelector:@selector(doSomethingWithMyAge:) withObject:42]; 

करने का प्रयास केवल संकलन नहीं होंगे। एनएसएनंबर को पास करना: 42 (42) के बजाय @ (42), या तो मदद नहीं करेगा, क्योंकि विधि मूल सी प्रकार की अपेक्षा करती है - ऑब्जेक्ट नहीं।

इसके अतिरिक्त, प्रदर्शन पैरामीटर 2 पैरामीटर तक नहीं हैं, और नहीं। जबकि विधियों के कई बार कई और पैरामीटर हैं।

मुझे पता चला है कि हालांकि performSelector की तुल्यकालिक वेरिएंट:

- (id)performSelector:(SEL)aSelector; 
- (id)performSelector:(SEL)aSelector withObject:(id)object; 
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; 

हमेशा एक ऑब्जेक्ट, मैं एक साधारण BOOL या NSUInteger भी लौटने में सक्षम था, और यह काम किया।

प्रदर्शन चयनकर्ता के दो मुख्य उपयोगों में से एक है गतिशील रूप से उस विधि का नाम लिखना जिसे आप निष्पादित करना चाहते हैं, जैसा कि पिछले उत्तर में बताया गया है। उदाहरण

SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age"); 
[object performSelector:method]; 

अन्य उपयोग के लिए, एसिंक्रोनस रूप से संदेश प्रेषण पर आपत्ति उठाने का, जो बाद में वर्तमान runloop पर निष्पादित किया जाएगा है। इसके लिए, कई अन्य प्रदर्शन चयनकर्ता प्रकार हैं।

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes; 
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; 
- (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes; 
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; 
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; 
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; 
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; 
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; 

(हाँ मैं उन्हें कई फाउंडेशन वर्ग श्रेणियों से इकट्ठा, NSThread, NSRunLoop और NSObject की तरह)

वेरिएंट से प्रत्येक की अपनी विशेष व्यवहार है, लेकिन आम में सभी शेयर कुछ (कम से कम जब waitUntilDone NO पर सेट है)। "प्रदर्शन चयनकर्ता" कॉल तुरंत वापस आ जाएगा, और ऑब्जेक्ट का संदेश केवल कुछ समय बाद वर्तमान रनलोप पर रखा जाएगा।

देरी निष्पादन की वजह से - स्वाभाविक रूप से कोई वापसी मूल्य चयनकर्ता की विधि के रूप में उपलब्ध नहीं है, इसलिए - इन सभी अतुल्यकालिक रूपों में - (शून्य) वापसी मूल्य।

मुझे आशा है कि मैं किसी भी तरह इस कवर ...

संबंधित मुद्दे