Ec अघोषित चयनकर्ता ’की चेतावनी से कैसे छुटकारा पाया जाए


162

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

if ([self respondsToSelector:@selector(setError:)])
{
    [self performSelector:@selector(setError:) withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}

हालाँकि, कंपाइलर को सेटर्र: सिग्नेचर: के साथ कोई भी विधि दिखाई नहीं देती है, इसलिए यह मुझे एक चेतावनी देता है, जिसमें प्रत्येक पंक्ति में @selector(setError:)स्निपेट होता है :

Undeclared selector 'setError:'

मैं इस चेतावनी से छुटकारा पाने के लिए एक प्रोटोकॉल की घोषणा नहीं करना चाहता, क्योंकि मैं उन सभी वर्गों को नहीं चाहता जो कुछ विशेष लागू करने के लिए इसका उपयोग कर सकते हैं। बस अधिवेशन से मैं चाहता हूं कि उनके पास एक setError:विधि या संपत्ति हो।

क्या यह करने योग्य है? कैसे?

चीयर्स,
ईपी


2
समाधान अच्छी तरह से
PerformSelector

एक चयनित चयनकर्ता चेतावनी का कारण होगा। चयनकर्ता तक पहुंचना सुरक्षित नहीं है क्योंकि चयनकर्ता को किसी समय हटाया जा सकता है।
डॉनसॉन्ग

जवाबों:


254

इसके साथ चेतावनी को निष्क्रिय करने का एक और विकल्प होगा:

#pragma GCC diagnostic ignored "-Wundeclared-selector"

आप इस लाइन को .m फ़ाइल में रख सकते हैं जहाँ चेतावनी होती है।

अपडेट करें:

यह इस तरह एलएलवीएम के साथ भी काम करता है:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"

... your code here ...

#pragma clang diagnostic pop

#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wundeclared-selector" // Do your thing #pragma clang diagnostic pop
dizy

हाँ, यह @dizy राज्यों के रूप में करता है। (देर से जवाब के लिए क्षमा करें, लेकिन मैं अधिसूचना से चूक गया)।
कलास

मुझे जरूरत है आगजनी#pragma clang diagnostic ignored "-Wselector"
अधिकतम

1
@mdorseif अधिकांश समय आपको 'बहिष्कृत' करने की चेतावनी संकलन लॉग में सूचीबद्ध होती है। आप इस अवधारणा के साथ किसी भी चेतावनी को म्यूट कर सकते हैं। खुशी है कि आपने चयनकर्ताओं के संबंध में अपना नाम जोड़ा।
काल

@epologee आप "अघोषित चयनकर्ता" सेटिंग के माध्यम से ऐसा ही कर सकते हैं

194

NSSelectorFromString पर एक नज़र डालें

 SEL selector = NSSelectorFromString(@"setError:");
 if ([self respondsToSelector:selector])

यह आपको @selectorकीवर्ड के माध्यम से संकलन समय के बजाय, रनटाइम पर एक चयनकर्ता बनाने की अनुमति देगा , और कंपाइलर के पास शिकायत करने का कोई मौका नहीं होगा।


हाय @sergio, आपके और @ jacobrelkin के उत्तर दोनों काम करते हैं। एक साथ बहुत अधिक प्रस्तुत किया। क्या आप मुझे 'बेहतर' उत्तर चुनने में मदद करेंगे, अगर कोई है?
epologee

2
मुझे यह उत्तर अधिक पसंद है क्योंकि यह अधिक "कोको" -y (?) दिखता है। sel_registerName()Thingy दिखता अस्पष्ट और तरह आप सीधे नहीं बुला किया जाना चाहिए जब तक आप जानते हैं कि आप क्या कर रहे हैं, obj_msg_send () की तरह थोड़े;)
निकोलस Miari

15
यकीन नहीं है कि यह Xcode 5 है, लेकिन मुझे इस कार्यान्वयन के साथ एक अलग चेतावनी मिल रही है: "PerformSelector एक रिसाव का कारण हो सकता है क्योंकि इसका चयनकर्ता अज्ञात है"
१६:३

1
@ Hampden123: यह एक अलग मुद्दा है। यहाँ एक नज़र है: stackoverflow.com/questions/7017281/…
सर्जियो

52

मुझे लगता है कि यह कुछ अजीब कारण के लिए चयनकर्ता रनटाइम के साथ पंजीकृत नहीं है।

चयनकर्ता को इसके माध्यम से पंजीकृत करने का प्रयास करें sel_registerName():

SEL setErrorSelector = sel_registerName("setError:");

if([self respondsToSelector:setErrorSelector]) {
   [self performSelector:setErrorSelector withObject:[NSError errorWithDomain:@"SomeDomain" code:1 userInfo:nil]];
}

हाय @jacobrelkin, आपके और @ सर्जियो के जवाब दोनों काम करते हैं। एक साथ बहुत अधिक प्रस्तुत किया। क्या आप मुझे 'बेहतर' उत्तर चुनने में मदद करेंगे, अगर कोई है?
epologee

2
@epologee वैसे भी हुड के तहत NSSelectorFromStringकॉल sel_registerName()करता है। जो भी आप बेहतर सूट चुनें।
जैकब रिलकिन

1
@epologee मुझे लगता है कि sel_registerName()सीधे कॉल करना अधिक स्पष्ट है कि आप ऐसा क्यों कर रहे हैं। आपको NSSelectorFromStringनहीं बताता कि यह चयनकर्ता को पंजीकृत करने का प्रयास करने जा रहा है।
जैकब रीकिन

8
यकीन नहीं है कि यह Xcode 5 है, लेकिन मुझे इस कार्यान्वयन के साथ एक अलग चेतावनी मिल रही है: "PerformSelector एक रिसाव का कारण हो सकता है क्योंकि इसका चयनकर्ता अज्ञात है"
हंप्डेन १२

@ Max_Power89 नहीं। मेरी अन्य टिप्पणियाँ नीचे देखें। मैं इस पर बहुत अधिक समय बिताना नहीं चाहता था, इसलिए मैंने केवल हेडर फ़ाइलों को शामिल किया।
हैम्पडेन123

7

मुझे वह संदेश मिला जिसमें # विधि द्वारा फ़ाइल को शामिल करना है। उस फ़ाइल से और कुछ भी उपयोग नहीं किया गया था।


जबकि यह कम सुंदर समाधान है, यह मेरे लिए काम करता है क्योंकि मेरे पास "ज्ञात संदिग्ध" हैं जो चयनकर्ता प्राप्त कर सकते हैं। इसके अलावा, यदि मैं रनटाइम चयनकर्ता दृष्टिकोण को लागू करता हूं, तो मुझे अभी भी प्रदर्शनकर्ता कथन पर एक अलग चेतावनी मिलेगी; अर्थात्, "PerformSelector एक रिसाव का कारण हो सकता है क्योंकि इसका चयनकर्ता अज्ञात है" । तो धन्यवाद!
हंप्डेन १२

2
न तो शीर्ष मतदान के उत्तर सही हैं। "अघोषित चयनकर्ता" चेतावनी का उद्देश्य संकलन समय पर त्रुटियों को पकड़ना है यदि आप उस चयनकर्ता का नाम बदलते हैं जिस पर आप भरोसा कर रहे थे। इसलिए यह उस फ़ाइल को #import करने के लिए सबसे सही है जो उस विधि की घोषणा करता है जिस पर आप भरोसा कर रहे थे।
ब्रैन

7

मुझे लगता है कि मुझे इस धागे में थोड़ी देर हो गई है लेकिन पूर्णता के लिए, आप लक्ष्य निर्माण सेटिंग्स का उपयोग करके विश्व स्तर पर इस चेतावनी को बंद कर सकते हैं।

अनुभाग में, 'Apple LLVM चेतावनियाँ - उद्देश्य-सी', बदलें:

Undeclared Selector - NO

6

यदि आपकी कक्षा setError को लागू करती है: विधि (भले ही अंतिम त्रुटि संपत्ति का सेटर डायनेमिक घोषित करके) आप इसे अपनी इंटरफ़ेस फ़ाइल (.h) में घोषित करना चाहते हैं, या यदि आप इसे उस तरह से दिखाना पसंद नहीं करते हैं जैसे आप कर सकते हैं। PrivateMethods मुश्किल चाल के साथ प्रयास करें:

@interface Yourclass (PrivateMethods)

- (void) yourMethod1;
- (void) yourMethod2;

@end

आपके @ कार्यान्वयन से ठीक पहले, यह चेतावनी छिपाई जानी चाहिए;)।


धन्यवाद, लेकिन मैं एक श्रेणी से विधि को बुला रहा हूं, इसलिए यह लागू नहीं होता है। चीयर्स, ईपी।
epologee

और हम में से कुछ ऐसी चीजें कर रहे हैं जो अधिक विदेशी हैं - चयनकर्ता को मेरे मामले में एफ # ऑब्जेक्ट में लागू किया गया है।
जेम्स मूर

1
यह XCode 7.1.1 / iOS 9.1 में चेतावनी से छुटकारा नहीं देता है, मैं देख सकता हूंPerformSelector may cause a leak because its selector is unknown
लोरेटोपरिसी

3

वास्तव में एक सहज मैक्रो अपने में डालने के लिए .pchया Common.hया जहाँ भी आप चाहते हैं:

#define SUPPRESS_UNDECLARED_SELECTOR_LEAK_WARNING(code)                        \
_Pragma("clang diagnostic push")                                        \
_Pragma("clang diagnostic ignored \"-Wundeclared-selector"\"")     \
code;                                                                   \
_Pragma("clang diagnostic pop")                                         \

यह इसी तरह के मुद्दे के लिए इस सवाल का एक संपादन है ...


3

आप स्क्रीनशॉट में Xcode की तरह इसे बंद कर सकते हैं:

यहां छवि विवरण दर्ज करें


अच्छा है। फिर भी, मैं केवल स्पष्ट मामलों के लिए चेतावनी को अक्षम करना पसंद करता हूं, कहने का मतलब है कि "इस अवसर में गलत है, मुझे पता है कि मैं क्या कर रहा हूं"। आपके सहयोग के लिए धन्यवाद!
एपोलोगी

2

चेतावनी से बचने के लिए आप किसी वस्तु को पहले आईडी में डाल सकते हैं:

if ([object respondsToSelector:@selector(myMethod)]) {
    [(id)object myMethod];
}

1
यह अभिव्यक्ति सामग्री पर समान चेतावनी से छुटकारा नहीं देता है, इस दिन XC7.1 तक सभी तरह से।
मार्टिन-गाइल्स लावोई

2

इस चेतावनी से बचने का एक और तरीका यह सुनिश्चित करना है कि आपका चयनकर्ता तरीका इस तरह दिखता है:

-(void) myMethod :(id) sender{
}

यदि आप किसी भी प्रेषक को स्वीकार करना चाहते हैं या यदि आप चाहें तो एक प्रेषक ऑब्जेक्ट को निर्दिष्ट करना चाहते हैं तो "(आईडी) प्रेषक" मत भूलना।


0

जबकि सही उत्तर की संभावना एक्सकोड को आयात के माध्यम से सूचित करने या चयनकर्ता को पंजीकृत करने की है कि इस तरह के चयनकर्ता मौजूद हैं, मेरे मामले में मैं एक अर्ध-उपनिवेश याद कर रहा था। सुनिश्चित करें कि इससे पहले कि आप "त्रुटि" ठीक कर लें, त्रुटि सही है और आपका कोड नहीं है। उदाहरण के लिए, मुझे Apple के MVCNetworking नमूने में त्रुटि मिली।


नहीं, सही उत्तर आयात के माध्यम से Xcode को सूचित करने में नहीं था, क्योंकि उन आयातों की जगह थी। सही उत्तर ऊपर का उत्तर था जो कि ... सही उत्तर के रूप में चिह्नित किया गया था, हालांकि @ सर्जियो का उत्तर भी समस्या को हल करेगा। गलत चयनकर्ता का उपयोग करना इस प्रश्न का विषय नहीं है, इसलिए चयनकर्ता को बदलना एक उत्तर नहीं है। मैं तुम्हें नीचे हालांकि बचा लेंगे।
एपोलोजी

1
मुझे याद दिलाने के लिए धन्यवाद कि मुझे शायद एक टिप्पणी का उपयोग करना चाहिए था। मैं केवल इतना कह सकता हूं कि लापता आयात भी इस Xcode चेतावनी का कारण बनता है, यदि यह विशिष्ट उदाहरण नहीं है। मैं केवल NSSelectorFromString या ऐसे अन्य "पंजीकरण" विकल्पों की सिफारिश करूंगा जब रनटाइम पर चयनकर्ता का निर्माण या डायनेमिक फ़ैशन में मेथड कॉल का जवाब देना (जैसे मेथडिसग्नेचर फ़ॉर सेलेक्टर)। इसे पंजीकृत करने का मतलब है कि आप "त्रुटि के आसपास काम कर रहे हैं" और इसलिए कुछ परिस्थितियों के लिए सही नहीं है, क्योंकि चेतावनी को ठीक करने के लिए एक अधिक सही तरीका होगा (यदि क्लैंग विश्लेषण सही था, वह है।)
लुई सेंट-अमौर।

वास्तव में, अब मैं देख रहा हूं कि मूल प्रश्न स्पष्ट रूप से कहता है, "एक कार्यान्वित प्रोटोकॉल की आवश्यकता के बिना" - और बिल्कुल भी आयात का उल्लेख नहीं करता है। इसलिए मैं आगे रखूंगा कि इस उपयोगकर्ता के लिए श्रेणी का आयात करना ही सबसे अच्छा विकल्प हो सकता है। यहाँ कुछ भी चयनकर्ता दो बार परिभाषित कर सकता है, तकनीकी रूप से बोल रहा है। हाँ? - संपादित करें: आह, मैंने यह बहुत दूर ले लिया है। आपकी प्रतिक्रिया के लिए धन्यवाद, मैं अभी रुकूंगा। :)
लुई सेंट-अमोर

-1

मैं सुखदायक पद्धति (प्रकटीकरण) जोड़कर दूर जाने की चेतावनी प्राप्त करने में सक्षम था: मैंने इस बारे में नहीं सोचा था, लेकिन इसे शिष्टाचार पर विचार करने से मिला।

    [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
                                     target:self
                                   selector:@selector(donothingatall:)
                                   userInfo:nil
                                    repeats:YES];


    [[NSRunLoop currentRunLoop] run];

    HTTPLogVerbose(@"%@: BonjourThread: Aborted", THIS_FILE);

    }
}

+ (void) donothingatall:(NSTimer *)timer
{

}

जबकि मैं यह जानना चाहता हूं कि चेतावनी को कैसे छिपाया जाए, इसे ठीक करना बेहतर है और न ही सर्जियो की न ही रिलकिन की तकनीकों ने मेरे लिए, अज्ञात कारणों से काम किया।


1
यदि कोई अन्य व्यक्ति इस समाधान को पढ़ता है, जो काम करेगा , तो वह आपके भविष्य के आत्म सहित बहुत भ्रमित होगा। यदि आप सुनिश्चित हैं कि आप जानते हैं कि आप एक गैर-मौजूदा चयनकर्ता को कॉल करके क्या कर रहे हैं, जिससे चेतावनी हो रही है, तो भ्रामक पद्धति को रोकें और सुनिश्चित करें कि आपका कोड आपके इरादे को व्यक्त करता है।
एपोलोजी

1
अच्छी बात। मैं विरासत में मिला कोड के साथ काम कर रहा था और सिर्फ यह पता लगाने की कोशिश कर रहा था कि चेतावनी को दूर कैसे किया जाए, गैर-मौजूद चयनकर्ता के मूल प्रश्न को हल करने की कोशिश क्यों नहीं की गई। एक समय में एक कदम, मैं हमेशा कहता हूं।
user938797
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.