उद्देश्य-सी में एक @protocol वर्ग के एक उदाहरण कास्ट करें


102

मेरे पास एक ऑब्जेक्ट (एक UIViewController) है जो मेरे द्वारा परिभाषित प्रोटोकॉल के अनुरूप हो सकता है या नहीं भी हो सकता है।

मुझे पता है कि मैं निर्धारित कर सकता हूं कि ऑब्जेक्ट प्रोटोकॉल के अनुरूप है, तो सुरक्षित रूप से विधि को कॉल करें:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)]) {
    [self.myViewController protocolMethod]; // <-- warning here
}

हालाँकि, XCode एक चेतावनी दिखाता है:

warning 'UIViewController' may not respond to '-protocolMethod'

इस चेतावनी को रोकने का सही तरीका क्या है? मैं self.myViewControllerएक MyProtocolवर्ग के रूप में कास्ट नहीं कर सकता ।

जवाबों:


171

ऐसा करने का सही तरीका है:

if ([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
        UIViewController <MyProtocol> *vc = (UIViewController <MyProtocol> *) self.myViewController;
        [vc protocolMethod];
}

UIViewController <MyProtocol> *टाइप-कास्ट करने के लिए अनुवाद, का उपयोग करते हुए, जबकि "vc एक UIViewController वस्तु MyProtocol के अनुरूप है कि है" id <MyProtocol>के लिए अनुवाद "vc एक अज्ञात वर्ग कि MyProtocol के अनुरूप की एक वस्तु है"।

इस तरह संकलक आपको उचित प्रकार की जाँच vcदेगा - संकलक आपको केवल एक चेतावनी देगा यदि कोई विधि जिसे UIViewControllerया तो घोषित नहीं किया गया है या <MyProtocol>कहा जाता है। idकेवल उस स्थिति में उपयोग किया जाना चाहिए जब आपको कक्षा के प्रकार / प्रकार का पता न हो।


2
प्रोटोकॉल का उपयोग करते समय आपको वास्तव में ऑब्जेक्ट प्रकार के बारे में परवाह नहीं करनी चाहिए - एक प्रोटोकॉल का पूरा बिंदु यह है कि कोई भी ऑब्जेक्ट प्रकार इसे अपना सकता है और विशिष्ट वस्तु के लिए डाले बिना उपयोग किया जा सकता है। तो, मैं आपको कहीं भी ऊपर एक प्रोटोकॉल के लिए कास्टिंग कर रहे हैं, तो @ कैंडी द्वारा जवाब का उपयोग करने की सिफारिश करेंगे - id<MyProtocol> p = (id<MyProtocol>)self.myViewController;यह उत्तर और @andys दोनों सही हैं, लेकिन उसका उपयोग अधिक सही है।
मेमन

2
@Answerbot आपकी टिप्पणी गलत है, और मेरे उत्तर के अंतिम पैराग्राफ में दिए गए बिंदु को याद करता है। आप ऑब्जेक्ट प्रकार के बारे में परवाह कर सकते हैं या नहीं कर सकते हैं, यह स्थिति पर निर्भर करता है। अगर आप किसी संदेश को घोषित भेजना चाहते हैं तो क्या होता है UIViewControllerकरने के लिए vcमेरा उत्तर में उदाहरण में है, और यह रूप में घोषित किया है id <MyProtocol>?
निक फोर्ज

सुनिश्चित नहीं हैं कि मेरी टिप्पणी के संबंध में क्या गलत है? किसी भी मामले में, यदि आप जाँच कर रहे हैं कि कोई वस्तु किसी प्रोटोकॉल के अनुरूप है तो आप प्रोटोकॉल के लिए असंबंधित किसी अन्य विधि को क्यों कहेंगे? मुझे यह याद करने की आवश्यकता नहीं है कि ऐसा करने की आवश्यकता है या इस कोड को देखकर मैंने इसकी समीक्षा की है। एक कोड गंध की तरह मुझे लगता है।
मेमन्स

सिर्फ इसलिए कि आपने इसे देखा / उपयोग नहीं किया है, इसका मतलब यह नहीं है कि यह कोड गंध है। यहां एक कोड स्निपेट दिखाया गया है, जहां एक प्रकार का उपयोग करके जानकारी फेंकने की जानकारी idएक समस्या है: gist.github.com/nsforge/7743616
Nick Forge

60

आप इसे इस तरह से डाल सकते हैं:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
    id<MyProtocol> p = (id<MyProtocol>)self.myViewController;
    [p protocolMethod];
}

यह मुझे एक बिट के लिए भी फेंक दिया। ऑब्जेक्टिव-सी में, प्रोटोकॉल स्वयं प्रकार नहीं है, इसलिए आपको उस प्रोटोकॉल के साथ id(या कुछ अन्य प्रकार, जैसे NSObject) निर्दिष्ट करना होगा जो आप चाहते हैं।


आह, शांत, धन्यवाद। मैंने अभी जाँच की और देखा कि यह (id)काम करता है। क्या वह बुरा रूप है?
Ford

1
यदि आप इसे आईडी <MyProtocol> के रूप में डालते हैं, तो कंपाइलर आपको चेतावनी देगा यदि आप उस प्रोटोकॉल में परिभाषित तरीकों का उपयोग नहीं करते हैं।
ड्रीमलैक्स

1
@dreamlax - यह संकलक प्रोटोकॉल के खिलाफ प्रकार की जाँच करता है। अधिक जानकारी के लिए डेवलपर .apple.com/documentation/Cocoa/Conceptual/ObjectiveC/… देखें ।
एंडी

1
@ फॉर्ड - प्रोटोकॉल का विशेष रूप से उपयोग करना बेहतर होगा, क्योंकि उस तरह से कंपाइलर आपके लिए कुछ प्रकार की जाँच कर सकता है।
एंडी

1
@ और, मुझे नहीं लगता कि आपको 'आईडी' की जरूरत है क्योंकि 'आईडी' पहले से ही एक पॉइंटर है। तो: id <MyProtocol> p = (id <MyProtocol>) self.myViewController; [पी प्रोटोकॉलमेथोड]; या बस: [(आईडी <MyProtocol>) self.myViewController प्रोटोकॉलMethod];
Ford
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.