Over a million developers have joined DZone.

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

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

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!

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.


Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}