2012-01-27 18 views
8

मैं शेयरकिट में इस कोड में आया, और मुझे समझ में नहीं आया कि लेखक को क्या समझ में आया था, self का उपयोग कक्षा विधि में किया गया था। एक चेतावनी है: पैरामीटर प्रकार id<FBSessionDelegate> पर 'कक्षा' भेजने वाले असंगत सूचक प्रकार। मैं इन चेतावनियों को साफ़ करना चाहता हूं, इसलिए मैं उन लोगों को देख सकता हूं जो बाद में चोट पहुंचा सकते हैं। मैं क्या कर सकता/सकती हूं जो इसे तोड़ नहीं पाएगी?वर्ग विधि में स्वयं का उपयोग

यह वह जगह है फ़ाइल SHKFacebook.m है और वर्ग के नाम SHKFacebook

+ (void)logout 
{ 
    FBSession *fbSession; 

    if(!SHKFacebookUseSessionProxy){ 
     fbSession = [FBSession sessionForApplication:SHKFacebookKey 
               secret:SHKFacebookSecret 
               delegate:self]; 

    }else { 
     fbSession = [FBSession sessionForApplication:SHKFacebookKey 
             getSessionProxy:SHKFacebookSessionProxyURL 
               delegate:self]; 
    } 

    [fbSession logout]; 
} 

उत्तर

13

self एक बहुरूपी कक्षा उदाहरण के रूप में एक वर्ग विधि में इस्तेमाल किया जा सकता है।

इसलिए वर्ग विधि new इस तरह लागू किया जा सकता:

+ (id)new 
{ 
    return [[self alloc] init]; 
} 

और कक्षा उदाहरण है कि संदेश भेजा है के लिए सही प्रकार वापसी होगी:

पूर्व एक:

NSArray * a = [NSArray new]; // << a is an NSArray 

पूर्व बी:

NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray 

नीचे नोट देखें।

तो आपको वास्तव में क्या सामना करना पड़ रहा है यह सुनिश्चित करना है कि प्रोटोकॉल में केवल उदाहरण विधियां हैं, और वह (वर्ग) स्वयं के तरीकों प्रोटोकॉल में उदाहरण विधियों को अपनाने के लिए मानचित्रण करते हैं।

जहां तक ​​डिज़ाइन ... अच्छा है, मान लीजिए कि मैं इसे इस तरह से नहीं लिखूंगा। एक सिंगलटन स्पष्ट और अधिक सही होता, लेकिन मुझे सिंगलेट्स भी पसंद नहीं आया, इसलिए मैं उस मार्ग को नहीं लेता।

चेतावनी उत्पादन किया जाता है क्योंकि कक्षा उदाहरण (क्या पारित हो जाता है) @protocoldelegate पैरामीटर द्वारा निर्दिष्ट अपनाने है। Class उदाहरण वर्ग का उदाहरण नहीं है। एक प्रोटोकॉल घोषणा वास्तव में कक्षा के उदाहरण पर लागू होती है। उदाहरण के लिए, यदि आप NSLocking अपनाते हैं, तो क्या संकलक आपको प्रोटोकॉल में घोषित प्रत्येक इंस्टेंस विधि के लिए क्लास विधियों को लागू करने की अपेक्षा करता है? उत्तर: कभी नहीं। जिस कार्यान्वयन के साथ आप काम कर रहे हैं वह आईएमओ उन मामलों में से एक है जहां यह भाषा का दुरुपयोग है, लेकिन यह काम करने के लिए होता है।

शब्दावली स्पष्ट करने के लिए:

"Class उदाहरण" एक वर्ग विधि में self है:

- (void)foo { self; } 
:

+ (void)foo { self; } 

एक "वर्ग के उदाहरण" एक उदाहरण विधि में self है

अभ्यास में, -[NSObject conformsToProtocol:]+[NSObject conformsToProtocol:] और +[NSObject class] बसदेता हैइसलिए निष्पादन में कोई त्रुटि नहीं है।

मैं अभी भी स्पष्ट नहीं हूं, फिर, मुझे चेतावनी क्यों मिल रही है, यदि कोड आपके द्वारा वर्णित मानदंडों को पूरा करता है।

मापदंड मैं वर्णित निष्पादन पर लागू होता है, लेकिन यह भाषा के शब्दों से भटक - इस प्रकार, संकलक इस पर पूरी तरह से सही है।

समस्या के लिए एक समाधान के लिए: वहाँ कोई रास्ता नहीं संकलक "मेरी क्लास उदाहरण प्रोटोकॉल के अनुरूप है" बताने के लिए क्योंकि गोद लेने की घोषणा वर्ग की उदाहरणों पर लागू होता है है।

  1. साफ, सही दृष्टिकोण: वर्ग का एक उदाहरण का उपयोग करें और के रूप में परिभाषित प्रोटोकॉल लागू

    आप दो प्राथमिक विकल्प हैं।

  2. या प्रोटोकॉल के वर्ग उदाहरण Typecast:

    आईडी प्रतिनिधि = (आईडी) स्व; fbSession = [FBSession sessionForAplication: SHKFacebookKey getSessionProxy: SHKFacebookSessionProxyURL प्रतिनिधि: प्रतिनिधि];

आप # 2 चुनते हैं, तो यह बहुत की तरह, कक्षा तरीकों का उपयोग करने के लिए प्रोटोकॉल के उदाहरण तरीकों परिभाषित करने में मदद कर सकते हैं:

+ (void)protocolMethod { /* do stuff */ } 
- (void)protocolMethod { [self.class protocolMethod]; } 

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

शोर को कम करने के लिए, आप भी कुछ विधि बनाने एक स्थान पर समान किरदार को कम करने पर विचार हो सकता है:

+ (id<SomeProtocol>)sharedSomeProtocolDelegate 
{ 
    return (id<SomeProtocol>)self; 
} 

- (id<SomeProtocol>)sharedSomeProtocolDelegate 
{ 
    return [[self class] sharedSomeProtocolDelegate]; 
} 

तो आप लिख सकते हैं:

fbSession = [FBSession sessionForApplication:SHKFacebookKey 
          getSessionProxy:SHKFacebookSessionProxyURL 
            delegate:[self sharedSomeProtocolDelegate]]; 

(ध्यान दें कि के कार्यान्वयन इन प्रकार वास्तव में कक्षा क्लस्टर हैं, और आप डीबगर में कुछ अलग देखेंगे या मुद्रित किए गए हैं)

+0

आपका संपादन स्पष्ट करता है। प्रोटोकॉल में केवल इंस्टेंस विधियां होती हैं और इनमें से कोई भी रिसीवर को संदर्भित नहीं करता है। मैं अभी भी स्पष्ट नहीं हूं, फिर, मुझे चेतावनी क्यों मिल रही है, अगर कोड आपके द्वारा वर्णित मानदंडों को पूरा करता है। – Jim

+0

@Jim विवरण जोड़ा गया – justin