1

I have a mixed Swift and Objective C application. The swift app uses some ObjectiveC libaries to handle OAuth2 authentication. Part of that is a callback to a delegate method once the OAuth2 request for a token has completed.

The following code is being executed in an Objective C library (GTMOAuth2) which uses a selector which I have passed in:

if (delegate_ && finishedSelector_) {
  SEL sel = finishedSelector_;
  NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel];
  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
  [invocation setSelector:sel];
  [invocation setTarget:delegate_];
  [invocation setArgument:&self atIndex:2];
  [invocation setArgument:&auth atIndex:3];
  [invocation setArgument:&error atIndex:4];
  [invocation invoke];
}

The function I'd like this to invoke is in my swift viewController and looks like such:

func authentication(viewController: GTMOAuth2ViewControllerTouch, finishedWithAuth: GTMOAuth2Authentication, error: NSError)
{
    if (error != nil)
    {
        var alertView: UIAlertView = UIAlertView(title: "Authorisation Failed", message: error.description, delegate: self, cancelButtonTitle: "Dismiss")

        alertView.show()

    }
    else
    {
        // Authentication Succeeded
        self.mytoken = finishedWithAuth.accessToken
    }
}

The selector I am currently passing in is:

let mySelector: Selector = Selector("authentication:viewController:finishedWithAuth:error:")

and is being used as a parameter in this call:

let myViewController: GTMOAuth2ViewControllerTouch = GTMOAuth2ViewControllerTouch(authentication: auth, authorizationURL: authURL, keychainItemName: nil, delegate: self, finishedSelector: mySelector)

Can anyone tell me why my function is never being called? It always seems to fail on the line where it creates an NSInvocation.

I've tried multiple selector strings and each one seems to fail. Am I missing something?

I've also tried putting "@objc" in front of the func name, to no avail.

Gareth Oates
  • 399
  • 4
  • 14
  • 1
    I assume that it should be `Selector("authentication:finishedWithAuth:error:")` but cannot test it at the moment. – Martin R Jun 30 '14 at 10:57
  • @Martin's assumption is correct, i have tested it. Selector should be `Selector("authentication:finishedWithAuth:error:")` – Anil Varghese Jun 30 '14 at 11:16

2 Answers2

5

The Swift method

func authentication(viewController: GTMOAuth2ViewControllerTouch,
                  finishedWithAuth: GTMOAuth2Authentication,
                             error: NSError)

is exposed to Objective-C as

-(void)authentication:(GTMOAuth2ViewControllerTouch *) viewController 
     finishedWithAuth:(GTMOAuth2Authentication *) finishedWithAuth
                error:(NSError *)error

which means that the selector is

Selector("authentication:finishedWithAuth:error:")

Generally, the first parameter name is not part of the selector. The only exception are init methods, where the first parameter name is merged into the Objective-C method name. For example, the Swift initializer

init(foo: Int, bar: Int) 

translates to Objective-C as

- (instancetype)initWithFoo:(NSInteger)foo bar:(NSInteger)bar

and the selector would be

Selector("initWithFoo:bar:")
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Tested it and it is indeed like Martin R said.

let mySelector: Selector = Selector("authentication:finishedWithAuth:error:")

The first parameter for swift function is generally nameless when looked at it's selector.

carlossless
  • 1,171
  • 8
  • 23