Note that there are some explanatory texts on larger screens.

plurals
  1. POWhen using Objection, implementation of custom protocol crashes with unrecognized selector
    primarykey
    data
    text
    <p>I am defining a custom protocol:</p> <pre><code>@protocol NGSAuthProvider &lt;NSObject&gt; - (BOOL)isReady; - (BOOL)isSessionValid; - (void)login; - (void)logout; - (NSString *)accessToken; - (BOOL)handleOpenURL:(NSURL *)url; @end </code></pre> <p>I want to have different providers. So one is a Facebook provider:</p> <pre><code>@interface NGSFacebookAuthProvider : NSObject &lt;NGSAuthProvider&gt; @end @interface NGSFacebookAuthProvider () &lt;FBSessionDelegate&gt; @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 </code></pre> <p>I setup <a href="https://github.com/atomicobject/objection">Objection</a> to bind from my class to the protocol.</p> <pre><code>@interface NGSObjectionModule : ObjectionModule @end @implementation NGSObjectionModule - (void)configure { self bind:[NGSFacebookAuthProvider class] toProtocol:@protocol(NGSAuthProvider)]; } @end </code></pre> <p>I setup the Global Injector:</p> <pre><code>@implementation NGSAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ObjectionModule *module = [[NGSObjectionModule alloc] init]; ObjectionInjector *injector = [Objection createInjector:module]; [module release]; [Objection setGlobalInjector:injector]; } </code></pre> <p>I am using this in my RootViewController like this:</p> <pre><code>@interface RootViewController : UITableViewController @end @interface RootViewController () @property(nonatomic, retain) id&lt;NGSAuthProvider&gt; 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 </code></pre> <p>When I run this, I get the following error:</p> <pre><code>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 </code></pre> <p>So my class implements the protocol. It successfully is assigned to <code>id&lt;NGSAuthProvider&gt;</code>. I tried contructing <code>[[NGSFacebookAuthProvider alloc] init]</code> explicitly instead of using <a href="https://github.com/atomicobject/objection">Objection</a> and it still crashed.</p> <p>I tried looping through the selectors using <code>objc/runtime.h</code> methods to see which selectors are there but the only thing it finds is <code>initialize</code>:</p> <pre><code>- (void)logSelectors:(id)obj { int i=0; unsigned int mc = 0; Method * mlist = class_copyMethodList(object_getClass([obj class]), &amp;mc); NSLog(@"%d methods", mc); for(i=0;i&lt;mc;i++) NSLog(@"Method no #%d: %s", i, sel_getName(method_getName(mlist[i]))); free(mlist); } </code></pre> <p>This has to be something simple that I am missing. I use protocols defined by Cocoa and don't have this issue. I have defined custom protocols for <code>UIViewController</code>-based delegates without issue.</p> <p>I am stumped as to why Obj-C runtime can't find my methods! If I change <code>id&lt;NGSAuthProvider&gt;</code> to <code>NGSFacebookAuthProvider</code> and construct it explicitly then it all works.</p> <p>SOLUTION:</p> <p>The problem was I misunderstood how to bind to a protocol. One way that works is:</p> <pre><code>@implementation NGSObjectionModule - (void)configure { [self bind:[[[NGSFacebookAuthProvider alloc] init] autorelease] toProtocol:@protocol(NGSAuthProvider)]; } @end </code></pre> <p>What I would like to do is bind a class to a protocol, but Objection probably wouldn't know the initializer to call?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload