Ambiguous reference when using selectors

Viewed 528

Ready to use example to test in Playgrounds:

import Foundation

class Demo {

    let selector = #selector(someFunc(_:))

    func someFunc(_ word: String) {
        // Do something
    }

    func someFunc(_ number: Int) {
        // Do something
    }

}

I'm getting an Ambiguous use of 'someFunc' error.

I have tried this answer and getting something like:

let selector = #selector(someFunc(_:) as (String) -> Void)

But still getting the same result.

Any hints on how to solve this?

2 Answers

Short answer: it can't be done.

Long explanation: when you want to use a #selector, the methods need to be exposed to Objective-C, so your code becomes:

@objc func someFunc(_ word: String) {
    // Do something
}

@objc func someFunc(_ number: Int) {
    // Do something
}

Thanks to the @objc annotation, they are now exposed to Objective-C and an compatible thunk is generated. Objective-C can use it to call the Swift methods.

In Objective-C we don't call a method directly but instead we try to send a message using objc_msgSend: the compiler is not able to understand that those method are different, since the generated signature is the same, so it won't compile. You will face the error:

Method 'someFunc' with Objective-C selector 'someFunc:' conflicts with previous declaration with the same Objective-C selector.

The only way to fix it is to have different signatures, changing one or both of them.

The selector is obviously ambiguous, neither methods have external parameter names. Remove the empty external parameters to solve this:

@objc func someFunc(word: String) {
    // Do something
}

@objc func someFunc(number: Int) {
    // Do something
}

After that, you should specify a selector with the parameter name:

#selector(someFunc(word:))

or

#selector(someFunc(number:))
Related