Question

Using Xamarin to create a binding library for some external code, I've encountered a problem where despite (as far as I can tell) implementing all of the selectors in a protocol, in Obj-C code, my delegate fails to pass a conformsToProtocol check and, as a result, the code doesn't work.

Here's what the Objective-C header file looks like (https://github.com/janrain/jump.ios/blob/master/Janrain/JRCapture/Classes/JRCapture.h):

@protocol JRCaptureDelegate <NSObject>
@optional
- (void)engageAuthenticationDialogDidFailToShowWithError:(NSError *)error;

- (void)engageAuthenticationDidCancel;

- (void)engageAuthenticationDidSucceedForUser:(NSDictionary *)engageAuthInfo forProvider:(NSString *)provider;

 - (void)engageAuthenticationDidFailWithError:(NSError *)error forProvider:(NSString *)provider;

- (void)captureSignInDidSucceedForUser:(JRCaptureUser *)captureUser
                            status:(JRCaptureRecordStatus)captureRecordStatus;

- (void)captureSignInDidFailWithError:(NSError *)error;

- (void)registerUserDidSucceed:(JRCaptureUser *)registeredUser;

- (void)registerUserDidFailWithError:(NSError *)error;

- (void)refreshAccessTokenDidSucceedWithContext:(id <NSObject>)context;

- (void)refreshAccessTokenDidFailWithError:(NSError *)error context:(id <NSObject>)context;
@end

And here's the part of the ApiDefinition.cs that corresponds to it:

[Model, BaseType (typeof (NSObject))]
public partial interface JRCaptureDelegate {

    [Export ("engageAuthenticationDidCancel")]
    void EngageAuthenticationCancelled ();

    [Export ("engageAuthenticationDidSucceedForUser:forProvider:")]
    void AuthenticationSucceededForProvider (NSDictionary engageAuthInfo, string provider);

    [Export ("captureSignInDidSucceedForUser:status:")]
    void SignInSucceeded (JRCaptureUser captureUser, JRCaptureRecordStatus captureRecordStatus);

    [Export ("registerUserDidSucceed:")]
    void  RegisterUserSucceeded(JRCaptureUser registeredUser);

    [Export ("refreshAccessTokenDidSucceedWithContext:")]
    void  RefreshAccessTokenSucceeded(NSObject context);

    //- (void)engageAuthenticationDialogDidFailToShowWithError:(NSError *)error
    [Export ("engageAuthenticationDialogDidFailToShowWithError:")]
    void DialogFailedToShow (NSError error);

    //- (void)engageAuthenticationDidFailWithError:(NSError *)error forProvider:(NSString *)provider;
    [Export("engageAuthenticationDidFailWithError:forProvider:")]
    void AuthenticationFailedForProvider (NSError error, NSString provider);

    //- (void)captureSignInDidFailWithError:(NSError *)error;
    [Export("captureSignInDidFailWithError:")]
    void SignInFailed (NSError error);

    //- (void)registerUserDidFailWithError:(NSError *)error;
    [Export("registerUserDidFailWithError:")]
    void RegisterUserFailed (NSError error);

    //- (void)refreshAccessTokenDidFailWithError:(NSError *)error context:(id <NSObject>)context;
    [Export("refreshAccessTokenDidFailWithError:context:")]
    void RefreshAccessTokenFailed (NSError error, NSObject context);
}

This compiles and appears to work just fine except I was having a problem with one particular method that didn't appear to want to call the methods in my delegate class. After a lot of digging (and learning Objective-C the hard way), I believe I have isolated the problem. In the library I'm binding, I have this:

    if ([delegate conformsToProtocol:@protocol(JRCaptureDelegate)] &&
        [delegate respondsToSelector:@selector(captureSignInDidSucceedForUser:status:)])

And with a little DLoging, I find that my delegate fails the conformsToProtocol check (although it does pass the respondsToSelector check).

So why does my class fail conformsToProtocol when it does implement all the methods in the protocol. What am I missing here?

My class implementing the delegate that gets passed to the various methods that take a JRCaptureDelegate just looks like this:

public class SignIn : JRCaptureDelegate
{
     // overrides for each method
}
Was it helpful?

Solution

Okay, think I might have cracked it. I added the Adopts attribute to my class (which is vaguely mentioned in various places in the Xamarin documentation, but not really suggested as something to do when creating a binding library). So now I have this:

[Adopts("JRCaptureDelegate")] 
public class SignIn : JRCaptureDelegate
{
     // overrides for each method
}

And it now passes the conformsToProtocol check. I'm not sure why this isn't automatic since I'm implementing the JRCaptureDelegate interface/protocol.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top