Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Properly Typed Selectors in Xcode 7.3 Beta 4

DZone's Guide to

Properly Typed Selectors in Xcode 7.3 Beta 4

Selectors can now be constructed from directly with the #selector expression.

· Mobile Zone ·
Free Resource

How many times have you had some innocuous looking code like this:


    let button = UIButton(type: .InfoDark)
    button.addTarget(self, action: "showInfo", forControlEvents: .TouchDown)

...which compiles without a problem but throws a runtime error when the hapless user touches the button:


    Terminating app due to uncaught exception 'NSInvalidArgumentException', 

    reason: '-[__lldb_expr_20.SelectorDemo showInfo]: unrecognized selector 

    sent to instance 0x7ffb3a414ac0'

The runtime error is caused by Swift not being able to find the showInfo function or maybe there is a showInfo, but it expects an argument. The root cause is, of course, the action argument of addTarget is being passed the string literal showInfo rather than a properly typed object. 

Well, with Xcode 7.3 beta 4, that problem is resolved! Selectors can now be constructed from directly with the#selector expression. In practice, this means that if your code has a function that looks like this:

    func showInfo(button: UIButton)
    {
        print("showInfo(_:)", button.debugDescription)
    }

We can add a target to the button with the following syntax:

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

    button.addTarget(self, action: selector, forControlEvents: .TouchDown)

If showInfo takes no arguments...

    func showInfo()
    {
 print("one: showInfo()")
    }

...the syntax is slightly different:

    let selector = #selector(SelectorDemo.showInfo as (SelectorDemo) -> () -> ())

Either way, the great advantage is that if the method name doesn't exist or the arguments are different, we get an error at compile time rather than runtime:

    let selectorTwo = #selector(displayInfo(_:))

    // results in:


    Playground execution failed: SelectorPlayground.playground:20:37: error: use of unresolved     

    identifier 'displayInfo'

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

                                 ^~~~~~~~~~~



I've created a small playground to demonstrate this new feature - it obviously needs Xcode 7.3 beta 4 - which is available at my GitHub repository.  Enjoy!

Topics:
xcode

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}