मैं अभी भी ऑब्जेक्टिव-सी के लिए नया हूं और मैं सोच रहा हूं कि निम्नलिखित दो कथनों में क्या अंतर है?
[object performSelector:@selector(doSomething)];
[object doSomething];
मैं अभी भी ऑब्जेक्टिव-सी के लिए नया हूं और मैं सोच रहा हूं कि निम्नलिखित दो कथनों में क्या अंतर है?
[object performSelector:@selector(doSomething)];
[object doSomething];
जवाबों:
मूल रूप से performSelector आपको गतिशील रूप से यह निर्धारित करने की अनुमति देता है कि चयनकर्ता किस ऑब्जेक्ट पर दिए गए चयनकर्ता को कॉल करे। दूसरे शब्दों में चयनकर्ता को रनटाइम से पहले निर्धारित नहीं किया जाना चाहिए।
इस प्रकार भले ही ये समतुल्य हों:
[anObject aMethod];
[anObject performSelector:@selector(aMethod)];
दूसरा रूप आपको ऐसा करने की अनुमति देता है:
SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector: aSelector];
इससे पहले कि आप संदेश भेजें।
performSelector:
कुछ आप शायद ही अगर आप अपने वर्ग में लक्ष्य कार्रवाई को लागू करना है। भाई बहन performSelectorInBackground:withObject:
और performSelectorOnMainThread:withObject:waitUntilDone:
अक्सर अधिक उपयोगी होते हैं। बैकग्राउंड थ्रेड को स्पैनिंग के लिए, और बैकग्राउंड थ्रेड से मुख्य थ्रेड पर कॉल करने के लिए।
performSelector
संकलित चेतावनियों को दबाने के लिए भी उपयोगी है। यदि आप जानते हैं कि विधि मौजूद है (जैसे उपयोग करने के बाद respondsToSelector
), तो यह Xcode को यह कहने से रोक देगा कि "जवाब नहीं दे सकता है your_selector
"। चेतावनी के वास्तविक कारण का पता लगाने के बजाय इसका उपयोग न करें । ;)
प्रश्न में इस मूल उदाहरण के लिए,
[object doSomething];
[object performSelector:@selector(doSomething)];
जो होने वाला है, उसमें कोई अंतर नहीं है। doSomething वस्तु द्वारा सिंक्रोनाइज़ की जाएगी। केवल "doSomething" एक बहुत ही सरल विधि है, जो कुछ भी वापस नहीं करता है, और किसी भी पैरामीटर की आवश्यकता नहीं है।
क्या यह कुछ अधिक जटिल था, जैसे:
(void)doSomethingWithMyAge:(NSUInteger)age;
चीजें जटिल हो जाएंगी, क्योंकि [वस्तु doSomethingWithMyAge: 42];
अब "performSelector" के किसी भी संस्करण के साथ नहीं बुलाया जा सकता है, क्योंकि मापदंडों वाले सभी संस्करण केवल ऑब्जेक्ट पैरामीटर स्वीकार करते हैं।
चयनकर्ता यहाँ "doSomethingWithMyAge:" होगा, लेकिन किसी भी प्रयास के लिए
[object performSelector:@selector(doSomethingWithMyAge:) withObject:42];
बस संकलन नहीं होगा। एक NSNumber पास करना: 42 के बजाय @ (42), या तो मदद नहीं करेगा, क्योंकि विधि एक बुनियादी सी प्रकार की उम्मीद करती है - एक वस्तु नहीं।
इसके अलावा, प्रदर्शन पैरामीटर 2 पैरामीटर तक हैं, कोई अधिक नहीं। जबकि कई बार तरीकों में कई और पैरामीटर होते हैं।
मुझे पता चला है कि हालांकि प्रदर्शन के तुल्यकालिक वेरिएंट:
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
हमेशा एक वस्तु वापस करें, मैं एक साधारण BOOL या NSUInteger भी वापस करने में सक्षम था, और यह काम किया।
PerformSelector के दो मुख्य उपयोगों में से एक गतिशील रूप से उस विधि का नाम लिखना है जिसे आप निष्पादित करना चाहते हैं, जैसा कि पिछले उत्तर में बताया गया है। उदाहरण के लिए
SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age");
[object performSelector:method];
अन्य उपयोग, अतुल्यकालिक रूप से एक संदेश को वस्तु के लिए भेजना है, जिसे बाद में वर्तमान रनअप पर निष्पादित किया जाएगा। इसके लिए, कई अन्य परफॉर्मर वेरिएंट हैं।
- (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)
प्रत्येक संस्करण का अपना विशेष व्यवहार होता है, लेकिन सभी कुछ साझा करते हैं (कम से कम जब waUntilDone NO पर सेट होता है)। "PerformSelector" कॉल तुरंत वापस आ जाएगी, और ऑब्जेक्ट पर संदेश केवल कुछ समय बाद चालू रनलूप पर रखा जाएगा।
विलंबित निष्पादन के कारण - स्वाभाविक रूप से कोई वापसी मूल्य उपलब्ध नहीं है, चयनकर्ता की विधि है, इसलिए - (शून्य) इन सभी अतुल्यकालिक वेरिएंट में वापसी मूल्य।
मुझे उम्मीद है कि मैंने इसे किसी तरह कवर किया ...
@ennuikiller पर हाजिर है। मूल रूप से, गतिशील रूप से उत्पन्न चयनकर्ता आपके लिए उपयोगी होते हैं जब आप (और आमतौर पर संभवतः नहीं कर सकते हैं) उस विधि का नाम जानते हैं जिसे आप कोड संकलित करते समय कॉल करेंगे।
एक महत्वपूर्ण अंतर यह है कि -performSelector:
दोस्त और ( बहु-थ्रेडेड और विलंबित वेरिएंट सहित ) कुछ हद तक सीमित हैं कि वे 0-2 मापदंडों वाले तरीकों के साथ उपयोग के लिए डिज़ाइन किए गए हैं। उदाहरण के लिए, -outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:
6 मापदंडों के साथ कॉल करना और वापस लौटना NSString
बहुत कठिन है, और प्रदान की गई विधियों द्वारा समर्थित नहीं है।
NSInvocation
वस्तु का उपयोग करना होगा ।
performSelector:
और दोस्त सभी ऑब्जेक्ट तर्क लेते हैं, जिसका अर्थ है कि आप उन्हें कॉल नहीं कर सकते हैं (उदाहरण के लिए) setAlphaValue:
, क्योंकि इसका तर्क एक फ्लोट है।
चयनकर्ता अन्य भाषाओं में फ़ंक्शन पॉइंट की तरह होते हैं। आप उन्हें उपयोग करते हैं जब आप संकलन समय पर नहीं जानते हैं कि आप किस समय रनटाइम पर कॉल करना चाहते हैं। साथ ही, फ़ंक्शन पॉइंटर की तरह, वे केवल आह्वान के क्रिया भाग को एनकैप्सुलेट करते हैं। यदि विधि में पैरामीटर हैं, तो आपको उन्हें भी पास करना होगा।
एक NSInvocation
समान उद्देश्य को पूरा करता है, सिवाय इसके कि यह अधिक जानकारी को एक साथ बांधता है। न केवल इसमें क्रिया भाग शामिल है, इसमें लक्ष्य ऑब्जेक्ट और पैरामीटर भी शामिल हैं। यह तब उपयोगी होता है जब आप किसी विशेष ऑब्जेक्ट पर किसी पैरामीटर को विशेष मापदंडों के साथ कॉल करना चाहते हैं, अब नहीं बल्कि भविष्य में। आप एक उपयुक्त निर्माण कर सकते हैं NSInvocation
और इसे बाद में आग लगा सकते हैं।
दोनों के बीच एक और सूक्ष्म अंतर है।
[object doSomething]; // is executed right away
[object performSelector:@selector(doSomething)]; // gets executed at the next runloop
यहाँ Apple प्रलेखन से अंश है
"performSelector: withObject: afterDelay: अगले रन लूप चक्र के दौरान और एक वैकल्पिक विलंब अवधि के दौरान वर्तमान थ्रेड पर निर्दिष्ट चयनकर्ता निष्पादित करता है। क्योंकि यह चयनकर्ता को निष्पादित करने के लिए अगले रन लूप चक्र तक इंतजार करता है, ये विधियाँ स्वत: मिनी विलंब प्रदान करती हैं। वर्तमान में क्रियान्वित कोड। कई कतारबद्ध चयनकर्ताओं को एक क्रम में एक के बाद एक प्रदर्शन किया जाता है। "
performSelector:withObject:afterDelay:
, लेकिन सवाल और आपके स्निपेट का उपयोग कर रहे हैं performSelector:
, जो एक पूरी तरह से अलग विधि है। इसके लिए डॉक्स से: <उद्धरण> performSelector:
विधि aSelector
सीधे रिसीवर को संदेश भेजने के बराबर है । </ उद्धरण>
performSelector/performSelector:withObject/performSelector:withObject:afterDelay
सभी ने उसी तरह का व्यवहार किया है जो एक गलती थी।