2011-01-01 13 views
18

जो मैंने अभी तक सीखा है: उद्देश्य-सी में आप किसी ऑब्जेक्ट को कोई संदेश भेज सकते हैं। यदि वस्तु सही तरीके को लागू करती है तो इसे निष्पादित किया जाएगा अन्यथा कुछ भी नहीं होगा। ऐसा इसलिए है क्योंकि संदेश भेजने से पहले उद्देश्य-सी प्रदर्शन करेगा प्रतिसाद देता है ToSelectorउद्देश्य-सी प्रतिक्रियाएं चयनकर्ता

मुझे उम्मीद है कि मैं अभी तक सही हूं।

मैंने परीक्षण के लिए एक छोटा सा कार्यक्रम किया जहां स्लाइडर स्थानांतरित होने पर हर बार कार्रवाई की जाती है। परीक्षण के लिए मैंने प्रेषक को एनएसबटन पर सेट किया लेकिन वास्तव में यह एक एनएसएसएलडर है। अब मैंने ऑब्जेक्ट से पूछा कि क्या यह setAlternateTitle का जवाब देगा। जबकि एक NSButton करेगा और NSSlider नहीं होगा। अगर मैं कोड चलाता हूं और प्रतिसाद देता हूं तो चयनकर्ता स्वयं यह मुझे बताएगा कि ऑब्जेक्ट उस चयनकर्ता का जवाब नहीं देगा। अगर मैं intValue जैसे कुछ और परीक्षण करता हूं, तो यह जवाब देगा। तो मेरा कोड अभी तक ठीक है।

- (IBAction)sliderDidMove:(id)sender 
{ 
    NSButton *slider = sender; 

    BOOL responds = 
    [slider respondsToSelector:@selector(setAlternateTitle)]; 

    if(responds == YES) 
    { 
     NSLog(@"YES");   
    } 
    else 
    { 
     NSLog(@"NO"); 
    } 

    [slider setAlternateTitle:@"Hello World"]; 
} 

लेकिन जब मैं वास्तव में सेटअल्टरनेट टाइटल संदेश भेजता हूं तो प्रोग्राम क्रैश हो जाएगा और मुझे बिल्कुल यकीन नहीं है कि क्यों। संदेश भेजने से पहले यह जवाब नहीं देना चाहिए?

उत्तर

146

सबसे पहले, विधि (उसके चयनकर्ता) के नाम में सभी सबपरेट्स और कोलन वर्ण शामिल हैं, जैसा कि एमवीडीएस ने कहा था।

दूसरा, विधि -respondsToSelector: रनटाइम द्वारा नहीं कहा जाता है, इसे आम तौर पर उपयोगकर्ता द्वारा स्वयं कहा जाता है (स्वयं या एपीआई जो जानना चाहते हैं कि एक प्रतिनिधि, उदाहरण के लिए, प्रोटोकॉल की वैकल्पिक विधि का जवाब देता है)।

जब आप किसी ऑब्जेक्ट को संदेश भेजते हैं, तो रनटाइम ऑब्जेक्ट के वर्ग (ऑब्जेक्ट के आईएसए पॉइंटर के माध्यम से) में विधि के कार्यान्वयन की तलाश करेगा। यह -respondsToSelector: भेजने के बराबर है हालांकि संदेश स्वयं प्रेषित नहीं किया गया है। यदि विधि का कार्यान्वयन कक्षा में या उसके सुपरक्लास में पाया जाता है, तो इसे आपके द्वारा पारित सभी तर्कों के साथ बुलाया जाता है।

यदि नहीं, तो रनटाइम संदेश को निष्पादित करने का दूसरा मौका देता है। यह ऑब्जेक्ट की कक्षा में + (BOOL)resolveInstanceMethod:(SEL)name संदेश भेजकर शुरू होगा: यह विधि आपको कक्षा में रनटाइम पर विधि जोड़ने की अनुमति देती है: यदि यह संदेश हाँ देता है, तो इसका मतलब है कि यह संदेश को फिर से ट्रैक कर सकता है।

यदि नहीं यह संदेश एक तिहाई का मौका देता निष्पादित किया जाना है, यह चयनकर्ता के साथ - (id)forwardingTargetForSelector:(SEL)aSelector भेजता है, इस विधि किसी अन्य वस्तु है कि वास्तविक रिसीवर की ओर से चयनकर्ता के लिए प्रतिक्रिया करने में सक्षम हो सकता लौट सकते हैं, अगर लौटे वस्तु जवाब दे सकता है, विधि निष्पादित की जाती है और मान वापस लौटाया जाता है जैसे कि यह मूल संदेश द्वारा वापस किया गया था। (नोट: यह ओएस एक्स 10.6 या आईओएस 4 के साथ शुरू हो रहा है।)

यदि लौटाया गया वस्तु शून्य या स्वयं (अनंत लूप से बचने के लिए) है, तो रनटाइम संदेश को विधि को निष्पादित करने का चौथा मौका देता है ... यह भेजता है एक आमंत्रण बनाने के लिए एक विधि हस्ताक्षर प्राप्त करने के लिए संदेश - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector। यदि कोई प्रदान किया जाता है तो संदेश - (void)forwardInvocation:(NSInvocation *)anInvocation संदेश के माध्यम से एक आमंत्रण भेजा जाता है। इस विधि में आप किसी भी तरीके से अन्य लक्ष्यों को भेजने के लिए आमंत्रण का विश्लेषण कर सकते हैं और अन्य संदेशों का निर्माण कर सकते हैं, और फिर आप आमंत्रण का वापसी मूल्य निर्धारित कर सकते हैं ... वह मान मूल संदेश के वापसी मूल्य के रूप में कार्य करेगा।

अंत में, यदि ऑब्जेक्ट द्वारा कोई विधि हस्ताक्षर नहीं लौटाया जाता है, तो रनटाइम आपके ऑब्जेक्ट पर - (void)doesNotRecognizeSelector:(SEL)aSelector संदेश भेजता है, एनएसओब्जेक्ट क्लास में इस विधि के कार्यान्वयन को अपवाद फेंकता है।

+0

+1। क्या आप कुछ लिंक प्रदान कर सकते हैं जहां यह पूरी प्रक्रिया विस्तार से दस्तावेज की गई है। यह पढ़ने लायक है। – taskinoor

+4

दस्तावेज़ यहां हैं: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html भाग में ... अन्य सामान NSObject क्लास संदर्भ – Psycho

+1

रास्ते में हैं , 'अग्रेषण लक्ष्यीकरण चयनकर्ता:' केवल मैक ओएस एक्स 10.6+ या आईओएस 4+ – user102008

7

एक बात के लिए, selector न केवल संदेश का "नाम" है, बल्कि यह भी है कि, यानी तर्क, और उनके नाम क्या हैं।

तो कुछ -(void)setAlternateTitle:(NSString*)str के लिए सही चयनकर्ता

@selector(setAlternateTitle:) 

:

आपकी समस्या के रूप में साथ होगा: एक वर्ग respondsToSelector() और आपको लगता है कि चयनकर्ता प्रदर्शन, तो आप एक नहीं मिलना चाहिए एक अज्ञात चयनकर्ता भेजने पर दुर्घटनाग्रस्त। डिबगिंग विंडो में आप किस तरह का क्रैश लॉग देखते हैं?

(ps। if (responds) { ... } सशर्त ब्लॉक में [slider setAlternateTitle:...] शामिल क्यों नहीं?)

+0

अधिक सटीक रूप से, एक चयनकर्ता में _ "निम्नानुसार, यानी तर्क, और उनके नाम" _ शामिल नहीं हैं, लेकिन "संदेश नाम के भीतर तर्कों की संख्या और स्थिति" शामिल नहीं है। –

2

"इसका कारण यह है इससे पहले कि संदेश है भेजा ऑब्जेक्टिव-सी respondsToSelector प्रदर्शन करेंगे।"

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

अगर मैं गलत हूं तो कृपया मुझे सही करें।

संपादित करें: यह सीधे आगे क्रैश नहीं है, लेकिन डिफ़ॉल्ट परिणाम यह है कि प्रक्रिया समाप्त हो जाएगी। संपूर्ण अनुक्रम टिप्पणी और अन्य उत्तर में पहले ही समझाया गया है, इसलिए मैं इसे फिर से लिखने वाला नहीं हूं।

+2

यह क्रैश नहीं होता है, यह * अग्रेषण * नामक प्रक्रिया पर वापस आ जाता है। दुर्भाग्यवश, यह अच्छी तरह से प्रलेखित नहीं प्रतीत होता है, लेकिन यह कई चीजें करता है: पहले यह रिसीवर की कक्षा पर '+ resolInstanceMethod:' को कॉल करता है। यदि यह विफल हो जाता है, तो यह '-forwardingTargetForSelector:' कहता है, फिर '-forwardInvocation:'। 'forforInvocation: 'का डिफ़ॉल्ट कार्यान्वयन एक अनुपूरक चयनकर्ता अपवाद फेंकता है, जो एक ही चीज नहीं है। –

+0

@ अरुमन, स्पष्टीकरण के लिए धन्यवाद। मुझे यह अनुक्रम नहीं पता था। यह वास्तव में सेगमेंटेशन गलती की तरह सीधे सीधी क्रैश नहीं है, लेकिन डिफ़ॉल्ट परिणाम लगता है कि प्रक्रिया समाप्त हो जाएगी। – taskinoor

+0

कम से कम मैं सही था कि विधि स्वचालित रूप से सिस्टम द्वारा नहीं बुलाया जाता है। इस उत्कृष्ट स्पष्टीकरण के लिए – taskinoor

1

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

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