Joseph DeCrisanti
Joseph DeCrisanti

Reputation: 33

How to pause Timer() when the app goes into the background

So I am stuck I am building a bingo app and I want the app to stop the timer when the app goes into the background. my code looks like this

var timer = Timer()

func ViewDidLoad(){
    // other stuff
    timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(numberPicker), userInfo: nil, repeats: true)
}

In other posts I've read about this I've seen people recommend defining timer as a weak variable. When I try this My app crashes when it try's to make the timer.

Upvotes: 2

Views: 1833

Answers (3)

vadian
vadian

Reputation: 285180

A modern solution is a DispatchSourceTimer which can be suspended and resumed.

The two notification observers use also modern swifty block based API, no @objc needed.

let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())

override func viewDidLoad() {
    super.viewDidLoad()
    timer.schedule(deadline: .now() + .seconds(5), repeating: 5.0)
    timer.setEventHandler {
        print("Timer fired")
    }

    NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { [weak self] _ in
        self?.timer.suspend()
    }
    NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { [weak self] _ in
        self?.timer.resume()
    }

    timer.activate()
}

Upvotes: 5

Fahim Rahman
Fahim Rahman

Reputation: 227

Swift 5:

override func viewDidLoad() {
        super.viewDidLoad()
        let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)
    }

    @objc func appMovedToBackground() {
        timer.invalidate()
    }

Upvotes: 1

rollingcodes
rollingcodes

Reputation: 16038

Try this. The timer will be restarted when the application returns from the background, as well.

class ViewController: UIViewController {

    var timer = Timer()
    var timerPaused = false

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default
            .addObserver(self,
                         selector: #selector(applicationDidEnterBackground),
                         name: UIApplication.didEnterBackgroundNotification,
                         object: nil)
        NotificationCenter.default
            .addObserver(self,
                         selector: #selector(applicationDidBecomeActive),
                         name: UIApplication.didBecomeActiveNotification,
                         object: nil)
        timer = Timer.scheduledTimer(timeInterval: 5,
                                     target: self,
                                     selector: #selector(numberPicker),
                                     userInfo: nil,
                                     repeats: true)
    }

    @objc
    func applicationDidEnterBackground(_ notification: Notification) {
        if !timerPaused {
            timer.invalidate()
            timerPaused = true
        }
    }

    @objc
    func applicationDidBecomeActive(_ notification: Notification) {
        if timerPaused {
            timer = Timer.scheduledTimer(timeInterval: 5,
                                     target: self,
                                     selector: #selector(numberPicker),
                                     userInfo: nil,
                                     repeats: true)
            timerPaused = false
        }
    }

    @objc
    func numberPicker(_ sender: Any) {

    }

}

Upvotes: 1

Related Questions