Continue countdown timer when app is running in background/suspended

前端 未结 4 870
灰色年华
灰色年华 2021-01-01 04:32

I have a functional countdown timer.

The problem is that I need to continue the countdown when the user puts the app in the background. Or suspends the app? I am no

相关标签:
4条回答
  • 2021-01-01 05:01

    Try this instead.. this code updates the time when app comes back from background/suspend and in active state..

    class ProgressV: UIView {

    var timer: NSTimer!
    var expirationDate = NSDate()
    
    //Set the time that you want to decrease..
    var numSeconds: NSTimeInterval = 36000.0 // Ex:10:00 hrs
    
    func startTimer()
    {
        // then set time interval to expirationDate…
        expirationDate = NSDate(timeIntervalSinceNow: numSeconds)
        timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(updateUI(_:)), userInfo: nil, repeats: true)
        NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
    
    }
    func updateUI(timer: NSTimer)
    {
      // Call the currentTimeString method which can decrease the time..
       let timeString = currentTimeString()
       labelName.text = timeString
    }
    func currentTimeString() -> String {
        let unitFlags: NSCalendarUnit = [.Hour, .Minute, .Second]
        let countdown: NSDateComponents = NSCalendar.currentCalendar().components(unitFlags, fromDate: NSDate(), toDate: expirationDate, options: [])
    
        var timeRemaining: String
        if countdown.hour > 0
        {
            timeRemaining = String(format: "%02d:%02d:%02d", countdown.hour, countdown.minute, countdown.second)
        }
        else {
            timeRemaining = String(format: "%02d:%02d:%02d", countdown.hour, countdown.minute, countdown.second)
        }
        return timeRemaining
    }
    

    }

    0 讨论(0)
  • 2021-01-01 05:09

    You shouldn't do that. A running timer keeps the device's processor running at full power, which is bad.

    Only certain types of apps are allowed to actually run code indefinitely from the background, e.g. VOIP apps and music apps.

    A couple of options:

    1. Set up a local notification for a future date (which will send a message to your app, or re-launch it if it was no longer running.)

    2. When you start your timer, record the current NSDate. Then, when your app returns to the foreground or gets re-launched, compare the current date to the saved date, figure out the amount of time that's elapsed, and decide if your timer is finished yet.

    0 讨论(0)
  • 2021-01-01 05:09

    Be sure that you turn on the background mode and set needed values in xCode. It is strange, but even if background mode is turned off, this code works. It seems to be work any timers after setting application.beginBackgroundTask {} in AppDelegate.

    I use this code:

    In AppDelegate add code below:

    func applicationDidEnterBackground(_ application: UIApplication) {
    
        application.beginBackgroundTask {} // allows to run background tasks
    }
    

    And call method below where you want.

    func registerBackgroundTask() {
        DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime.now() + 5, qos: .background) {
                print("fasdf")
            }
    }
    
    0 讨论(0)
  • 2021-01-01 05:18

    What I suggest is cancel the timer and store a NSDate when the app goes to the background. You can use this notification to detect the app going to the background:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseApp", name: UIApplicationDidEnterBackgroundNotification, object: nil)
    

    Then cancel the timer and store the date:

    func pauseApp(){
        self.stop() //invalidate timer
        self.currentBackgroundDate = NSDate()
    }
    

    Use this notification to detect the user coming back:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "startApp", name: UIApplicationDidBecomeActiveNotification, object: nil)
    

    Then calculate the difference from the stored date to the current date, update your counter and start the timer again:

    func startApp(){
        let difference = self.currentBackgroundDate.timeIntervalSinceDate(NSDate())
        self.handler(difference) //update difference
        self.start() //start timer
    }
    
    0 讨论(0)
提交回复
热议问题