2011-07-27 11 views
5

मैं एक कस्टम प्रोटोकॉल को परिभाषित कर रहा हूँ के साथ दुर्घटनाओं। प्रोटोकॉल के मेरी कक्षा से बाध्य करने के लिएआपत्ति का उपयोग करते समय, कस्टम प्रोटोकॉल के कार्यान्वयन के गैर मान्यता प्राप्त चयनकर्ता

@interface NGSFacebookAuthProvider : NSObject <NGSAuthProvider> 
@end 

@interface NGSFacebookAuthProvider() <FBSessionDelegate> 
@property BOOL ready; 
@property(nonatomic, retain) Facebook *facebook; 
@property(nonatomic, retain) NSArray *permissions; 
@end 

@implementation NGSFacebookAuthProvider 
//Implementation of fbLogin, fbLogout and the methods in NGSAuthProvider that forward calls to self.facebook 
- (NSString *)accessToken 
{ 
    return [self.facebook accessToken]; 
} 

@end 

मैं सेटअप Objection: तो एक एक Facebook प्रदाता है।

@interface NGSObjectionModule : ObjectionModule 
@end 

@implementation NGSObjectionModule 

- (void)configure 
{ 
    self bind:[NGSFacebookAuthProvider class] toProtocol:@protocol(NGSAuthProvider)]; 
} 
@end 

मैं सेटअप वैश्विक इंजेक्टर:

@implementation NGSAppDelegate 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    ObjectionModule *module = [[NGSObjectionModule alloc] init]; 
    ObjectionInjector *injector = [Objection createInjector:module]; 
    [module release]; 

    [Objection setGlobalInjector:injector]; 
} 

मैं इस तरह मेरी RootViewController में यह उपयोग कर रहा हूँ:

@interface RootViewController : UITableViewController 
@end 

@interface RootViewController() 
@property(nonatomic, retain) id<NGSAuthProvider> authProvider; 
@end 

@implementation RootViewController 
- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.authProvider = [[Objection globalInjector] getObject:@protocol(NGSAuthProvider)]; 
} 

- (void)processConfig { 
    NSString *token = [self.authProvider accessToken]; 
    // use the access token 
} 
@end 

जब मैं इस चलाने के लिए, मैं निम्नलिखित त्रुटि मिलती है:

2011-07-26 21:46:10.544 ngs[6133:b603] +[NGSFacebookAuthProvider accessToken]: unrecognized selector sent to class 0x30c7c 
2011-07-26 21:46:10.546 ngs[6133:b603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NGSFacebookAuthProvider accessToken]: unrecognized selector sent to class 0x30c7c' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x00e825a9 __exceptionPreprocess + 185 
    1 libobjc.A.dylib      0x00fd6313 objc_exception_throw + 44 
    2 CoreFoundation      0x00e8417b +[NSObject(NSObject) doesNotRecognizeSelector:] + 187 
    3 CoreFoundation      0x00df3966 ___forwarding___ + 966 
    4 CoreFoundation      0x00df3522 _CF_forwarding_prep_0 + 50 
    5 ngs         0x0000324b -[RootViewController processConfig] + 731 
    6 ngs         0x000041a2 __33-[RootViewController viewDidLoad]_block_invoke_0 + 50 

तो मेरी कक्षा आईएम प्रोटोकॉल plements। इसे सफलतापूर्वक id<NGSAuthProvider> पर असाइन किया गया है। मैंने का उपयोग Objection का उपयोग करने के बजाय स्पष्ट रूप से करने की कोशिश की और यह अभी भी दुर्घटनाग्रस्त हो गया।

- (void)logSelectors:(id)obj 
{ 
    int i=0; 
    unsigned int mc = 0; 
    Method * mlist = class_copyMethodList(object_getClass([obj class]), &mc); 
    NSLog(@"%d methods", mc); 
    for(i=0;i<mc;i++) 
     NSLog(@"Method no #%d: %s", i, sel_getName(method_getName(mlist[i]))); 

    free(mlist); 
} 

यह कुछ सरल है कि मुझे याद आ रही हो गया है:

मैं objc/runtime.h तरीकों का उपयोग कर जो चयनकर्ताओं देखते हैं लेकिन केवल एक चीज यह पाता है initialize है देखने के लिए चयनकर्ताओं के माध्यम से पाशन की कोशिश की। मैं कोको द्वारा परिभाषित प्रोटोकॉल का उपयोग करता हूं और यह समस्या नहीं है। मैंने बिना किसी मुद्दे के UIViewController-आधारित प्रतिनिधियों के लिए कस्टम प्रोटोकॉल परिभाषित किए हैं।

मुझे लगता है कि ओब्जे-सी रनटाइम मेरे तरीकों को क्यों नहीं ढूंढ सकता है! अगर मैं id<NGSAuthProvider> से NGSFacebookAuthProvider बदलता हूं और इसे स्पष्ट रूप से बना देता हूं तो यह सब काम करता है।

समाधान:

समस्या मैं गलत समझा एक प्रोटोकॉल के लिए बाध्य करने के लिए कैसे किया गया था। एक तरीका यह है कि काम करता है:

@implementation NGSObjectionModule 

- (void)configure 
{ 
    [self bind:[[[NGSFacebookAuthProvider alloc] init] autorelease] toProtocol:@protocol(NGSAuthProvider)]; 
} 
@end 

मैं करने के लिए एक प्रोटोकॉल के एक वर्ग के लिए बाध्य किया जाता है चाहते हैं क्या है, लेकिन आपत्ति शायद पता नहीं प्रारंभकर्ता कॉल करने के लिए?

+0

है हाय, मैं के लिए भेजा [http://ravelantunes.com/blog/ परिपक्व-निर्भरता इंजेक्शन /]। लेकिन [- (शून्य) कॉन्फ़िगर करें { [स्वयं बाइंड: [MyUserService क्लास] toProtocol: @protocol (UserService)]; }] कक्षा परिभाषित करने में त्रुटि है। आपका समाधान काम किया !!!! –

उत्तर

0

समस्या यह है कि आप अपनी ऑब्जेक्ट के उदाहरण पर चलने वाली विधि के बजाय स्थैतिक वर्ग विधि (निर्दिष्ट है क्योंकि आपके पास + + है) का उपयोग करने का प्रयास कर रहा है (जिसे आपने इसे लिखा है एक -)

+0

मुझे नहीं पता कि मैं कक्षा विधि का उपयोग कहां कर रहा हूं। – chrish

+0

मुझे या तो। लेकिन किसी भी तरह आप हैं, है ना? हो सकता है कि आपको लगता है कि आपके पास ऑब्जेक्ट का एक उदाहरण है लेकिन यह प्रकार के लिए एक पॉइंटर है (इस प्रकार क्लास विधियां मुझे लगता है कि हुड के तहत काम करती है) – Nektarios

+1

आप एक स्थिर क्लास विधि को कॉल करने के बारे में टिप्पणी करते हुए मुझे सोचते हैं। समस्या यह है कि मैं आपत्ति को कैसे कॉन्फ़िगर कर रहा हूं। मैंने सोचा था कि प्रोटोकॉल के लिए अनुरोध करते समय मैं इंस्टेंस को तत्काल करने के लिए क्लास ऑब्जेक्ट का उपयोग करने के लिए इसे स्थापित कर रहा था। इसे कॉन्फ़िगर करते समय मुझे वास्तव में एक उदाहरण बनाना होगा। समाधान को शामिल करने के लिए मैं प्रश्न अपडेट कर दूंगा। अब मैं डीबग आउटपुट में देखता हूं कि इसे '+ [NGSFacebookAuthProvider accessToken]' नहीं मिला। – chrish

0

क्रिस,

आपको लगता है कि आप एक प्रोटोकॉल पर मेटा वर्ग बाँध और मेटा वर्ग उदाहरण के खिलाफ वर्ग विधियां प्रारंभ करने की अनुमति देता है अनापत्ति के मेटा वर्ग बाइंडिंग का उपयोग कर सकते हैं।

उदाहरण के लिए

,

[self bindMetaClass:[NGSFacebookAuthProvider class] toProtocol:@protocol(NGSAuthProvider)]; 

लेकिन केवल आप वर्ग तरीकों का उपयोग करना चाहते हैं। अन्यथा आप शेयर इंस्टेंस के खिलाफ प्रोटोकॉल बाइंडिंग का उपयोग कर सकते हैं।

+0

मुझे पूरा यकीन नहीं है कि आप क्लास ऑब्जेक्ट में प्रोटोकॉल क्यों बांधेंगे। तो कक्षा वस्तु को प्रोटोकॉल को लागू करना होगा? – chrish

+0

प्रोटोकॉल मेटा क्लास के इंटरफ़ेस को दर्शाता है (वास्तव में यह नहीं है, लेकिन यदि आप नहीं करते हैं तो आपको कंपाइलर चेतावनियां मिलेंगी)। प्रोटोकॉल बस एक बाध्यकारी तंत्र के रूप में कार्य करता है ताकि आपत्ति को पता चले कि किस वस्तु को संपत्ति से बांधना है। चूंकि मेटा क्लास के इंटरफेस को प्रतिबिंबित करने वाली संपत्ति को परिभाषित करने का कोई तरीका नहीं है इसलिए प्रोटोकॉल का उपयोग ऐसा करने के लिए किया जाता है। देखें, https://github.com/atomicobject/objection और मेटा क्लास बाध्यकारी अनुभाग पढ़ें। – justice

+0

ठीक है, ठीक है कि मैं नहीं चाहता था (यानी वर्ग विधियों)। मेरे पास 'NGSAuthProvider 'प्रोटोकॉल के कई अलग-अलग कार्यान्वयन थे और प्रोटोकॉल के लिए अनुरोध किए जाने पर मैं विशिष्ट वर्ग के उदाहरण बनाने के लिए आपत्ति को कॉन्फ़िगर करना चाहता था। तो मैं '[स्वयं बाइंड: [एनजीएसफ़ेसबुकऑथप्रोवाइडर क्लास] टूप्रोटोकॉल चाहता था: @protocol (NGSAuthProvider)]' 'NGSFacebookAuthProvider' का उदाहरण बनाने के लिए आपत्ति का कारण बनता है लेकिन इसके बजाय क्लास ऑब्जेक्ट प्रदान करता है। – chrish

0

के रूप में मैं

उपयोग कर रहा था मैं भी यही मुद्दा का सामना करना पड़ा
[self bind:[MyClass class] toProtocol:@protocol(MyProtocol)]; 

यह काम करने के लिए सही तरीके से

[self bindClass:[MyClass class] toProtocol:@protocol(MyProtocol)]; 
संबंधित मुद्दे