Friday, April 15, 2016

Changes in Swift 2.2 - Selectors

Prior to Swift 2.2, you can use a string literal for Objective-C selectors. For example, in the following code snippet you could specify onTimer as the selector:

    func onTimer() {
        ...
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        delta = CGPointMake(12.0,4.0)
        NSTimer.scheduledTimerWithTimeInterval(0.05,
                                               target:self,
                                               selector:"onTimer",
                                               userInfo:nil,
                                               repeats:true)

    }

Because there is no checking to ensure that the selector name is a well-formed selector (or that it even refers to a valid method), this method of naming a selector is dangerous and hence deprecated in Swift 2.2. 

Instead, you should now use the new #selector expression that allows you to build a selector from a reference to a method. The above code now looks like this:

    override func viewDidLoad() {
        super.viewDidLoad()

        NSTimer.scheduledTimerWithTimeInterval(0.05,
                                               target:self,
                                               selector:#selector(ViewController.onTimer),
                                               userInfo:nil,
                                               repeats:true)
    }

If the target method accepts arguments, then the selector looks like this:

    func doSomething(num1:Int, num2:Int) {
        ...
    }

    override func viewDidLoad() {
        super.viewDidLoad()        
        
        NSTimer.scheduledTimerWithTimeInterval(0.05,
                                               target:self,
                                               selector:#selector(
                                               ViewController.doSomething(_:num2:)),
                                               userInfo:nil,
                                               repeats:true)
    }

While the old method of using string literal for selector is still supported in Swift 2.2, you should use the new syntax when updating your code.