swiftobjective-ccocoaselector

In what context can we use an unqualified #selector() expression in Swift?


The Swift equivalent of Objective-C's @selector() expression, is #selector(). In Xcode, the Objective-C, @selector() expression will offer autocompletions for all available selectors and the selector expression is constructed with just the selector; e.g., @selector(valueForKey:).

In Swift, Xcode only sometimes offers autocompletions for a #selector() expression and we must explicitly qualify the selector with a type; e.g., #selector(NSObject.value(forKey:)).

As far as I can tell, in an @objc context, Xcode will allow us to construct a #selector() expression without qualifying the selector with a type.

For example:

@objc @objcMembers class Individual: NSObject {
    func testFunc() {
        let sel = #selector(value(forKey:))
    }
}

Is there any other context in which we can use an #selector() expression that isn't qualified by a type?


Solution

  • The fully qualified selector name (with the class name) is not required, even in methods not marked with @objc. Of course the selector itself must be either an Objective-C method or a Swift method marked with @objc.

    Oddly, none of the documentation shows any example of a #selector without the fully qualified name but I never use the fully qualified name and it works just fine. It works just like it does in Objective-C. As long as the compiler can find such a method on any known class in the project, the unqualified selector can be used in any context.

    Relevant documentation (with no unqualified examples):

    BTW - Xcode does not force a fully qualified name for me. If I type something like:

    let sel = #selector(
    

    and then type a letter such as v, Xcode offers lots of selectors that start with a v but it does not include any class name.

    Also note that the selector name does not require the parentheses and arguments except in cases where you need to disambiguate between overloaded method names.

    As an example, let's say we have a button handler in some iOS code. We need the selector for the call to addTarget. The handler method may look like this:

    @objc func buttonTapped(_ button: UIButton) {
    }
    

    The following are all valid uses of #selector:

    #selector(SomeClass.buttonTapped(_:))
    #selector(SomeClass.buttonTapped)
    #selector(buttonTapped(_:))
    #selector(buttonTapped)
    

    And if the referenced selector is in the same class as the #selector line, you can also prefix the selector name with Self.:

    #selector(Self.buttonTapped(_:))
    #selector(Self.buttonTapped)
    

    though there seems to be little reason to do so.

    The main reason to fully qualify the selector name with the class name is to avoid runtime issues by ensuring, at compile time, that the referenced method actually exists on the specified class.