2017-09-17 Replacing NSTimer in Swift 4

Last edit

Summary: For repeated calling of a function, the Timer class is available (used to be called NSTimer). So perhaps you had the following code in your Swift 3 . . .

Changed:

< self.timerOld = Timer.scheduledTimer(

to

> self.timer = Timer.scheduledTimer(


For repeated calling of a function, the Timer class is available (used to be called NSTimer). So perhaps you had the following code in your Swift 3 project:

    private var timer: Timer?
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.timer = Timer.scheduledTimer(
            timeInterval: 1.0, target: self,
            selector: #selector(self.timerAction),
            userInfo: nil,
            repeats: true)
    }
    func timerAction() {
        // Do something
    }

When you move your project to Swift 4 (via Xcode 9), then first you get the following warning:

    The use of Swift 3 @objc inference in Swift 4 mode is deprecated. Please address deprecated @objc inference warnings, test your code with “Use of deprecated Swift 3 @objc inference” logging enabled, and then disable inference by changing the "Swift 3 @objc Inference" build setting to "Default" for the "blah" target.

You can fix this warning by updating the project settings and update the code as follows:

    @objc func timerAction() {
        // Do something
    }

For some reason, I don't like seeing that @objc in my projects. There's an alternative, and that's not to use Timer at all, but instead move to GCD:

    private let timer = DispatchSource.makeTimerSource()
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        timer.schedule(deadline: .now(), repeating: 1.0)
        timer.setEventHandler {
            DispatchQueue.main.sync {
                self.timerAction()
            }
        }
        timer.activate()
    }

Have fun with Swift 4 :)