0

I'm putting the finishing touches on my app, but the 5min countdown timer I have running pauses when the app goes to the background. I need an expert to help me solve this, every solution I read I could hardly understand.

I tried watching tutorials with other peoples code but it's hard to implement it to my own not knowing what I'm doing. Since I just borrowed code from someone on GitHub.

countdownTimer.delegate = self
    countdownTimer.setTimer(hours: 0, minutes: 0, seconds: selectedSecs)
    progressBar.setProgressBar(hours: 0, minutes: 0, seconds: selectedSecs)
    stopBtn.isEnabled = false
    stopBtn.alpha = 0.5

    view.addSubview(messageLabel)

    var constraintCenter = NSLayoutConstraint(item: messageLabel, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0)
    self.view.addConstraint(constraintCenter)
    constraintCenter = NSLayoutConstraint(item: messageLabel, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0)
    self.view.addConstraint(constraintCenter)

    messageLabel.isHidden = true
    counterView.isHidden = false
}

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}


//MARK: - Countdown Timer Delegate



func countdownTime(time: (hours: String, minutes: String, seconds: String)) {
    hours.text = time.hours
    minutes.text = time.minutes
    seconds.text = time.seconds
}


func countdownTimerDone() {

    counterView.isHidden = true
    messageLabel.isHidden = false
    seconds.text = String(selectedSecs)
    countdownTimerDidStart = false
    stopBtn.isEnabled = false
    stopBtn.alpha = 0.5
    startBtn.setTitle("START",for: .normal)
    AudioServicesPlaySystemSound(SystemSoundID(1300))


    print("countdownTimerDone")
}



//MARK: - Actions

@IBAction func startTimer(_ sender: UIButton) {

    messageLabel.isHidden = true
    counterView.isHidden = false

    stopBtn.isEnabled = true
    stopBtn.alpha = 1.0

    if !countdownTimerDidStart{
        countdownTimer.start()
        progressBar.start()
        countdownTimerDidStart = true
        startBtn.setTitle("PAUSE",for: .normal)


    }else{
        countdownTimer.pause()
        progressBar.pause()
        countdownTimerDidStart = false
        startBtn.setTitle("RESUME",for: .normal)
    }
}


@IBAction func stopTimer(_ sender: UIButton) {
    countdownTimer.stop()
    progressBar.stop()
    countdownTimerDidStart = false
    stopBtn.isEnabled = false
    stopBtn.alpha = 0.5
    startBtn.setTitle("START",for: .normal)
}

I tried using code to stop the timer when it goes to background and update it when it comes to foreground, but I can't find a way to capture the timer value when it closes

  • 1
    Take a look at [this answer](https://stackoverflow.com/a/50200606/1630618) for how to handle a timer when an app goes into the background. – vacawama Jun 21 '19 at 03:00
  • I want the timer to sound an alert, which it already does, but since it's a 5 minute timer no-one really leaves apps open for 5 minutes at a time. so it will pause and never sound the alert – Kyle Knoblauch Jun 21 '19 at 13:40
  • So, what you do is you schedule a local [user notification](https://developer.apple.com/documentation/usernotifications) so that the OS can show the user a message even if your app isn’t running. The user then has the opportunity to tap on the notification to open the app. And when the app is reopened, you use vacawama’s technique to have your timer handler look at the time to which the timer is counting down in order to update the UI accordingly. – Rob Jun 21 '19 at 17:39

1 Answers1

0

Try this in AppDelegate and manage your code in AppDelegate.

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var timerControl = 0
    var backgroundTaskIdentifier: UIBackgroundTaskIdentifier?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerCode), userInfo: nil, repeats: true)
        backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: {
        })
        return true
    }

    @objc func timerCode() {
        timerControl = timerControl + 1
        if timerControl == 5 {
            /// -> Do Something
        } else {
            /// -> Stop the task
            UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
        }
    }
}
  • Not sure how to implement this piece into my app delegate. Thanks for sharing – Kyle Knoblauch Jun 21 '19 at 14:05
  • You can use these codes in your controller. backgroundTaskIdentifier will help your timer work in the background. – Batuhan Göktepe Jun 21 '19 at 15:04
  • You can’t do that for five minutes. Plus, with no offense intended, even if you could, it’s a very inefficient solution to keep a timer ticking away when the user has left the app. – Rob Jun 21 '19 at 17:44