当应用程序在后台运行/挂起时继续倒数计时器

我有一个function倒计时器。

问题是我需要在用户将应用程序放在后台时继续倒计时。 或暂停应用程序? 我不确定用什么正确的术语来描述这个动作。

换句话说,用户打开应用程序并开始倒计时。 用户应该可以使用其他的应用程序,但倒计时仍然运作。 此外,倒计时应能够永久运行,直到完成或用户终止运行应用程序。

这里是我的计时器的代码:

class Timer{ var timer = NSTimer(); // the callback to be invoked everytime the timer 'ticks' var handler: (Int) -> (); //the total duration in seconds for which the timer should run to be set by the caller let duration: Int; //the amount of time in seconds elapsed so far var elapsedTime: Int = 0; var targetController = WaitingRoomController.self var completionCallback: (() -> Void)! /** :param: an integer duration specifying the total time in seconds for which the timer should run repeatedly :param: handler is reference to a function that takes an Integer argument representing the elapsed time allowing the implementor to process elapsed time and returns void */ init(duration: Int , handler : (Int) -> ()){ self.duration = duration; self.handler = handler; } /** Schedule the Timer to run every 1 second and invoke a callback method specified by 'selector' in repeating mode */ func start(){ self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "onTick", userInfo: nil, repeats: true); } /** invalidate the timer */ func stop(){ println("timer was invaidated from stop()") timer.invalidate(); } /** Called everytime the timer 'ticks'. Keep track of the total time elapsed and trigger the handler to notify the implementors of the current 'tick'. If the amount of time elapsed is the same as the total duration for the timer was intended to run, stop the timer. */ @objc func onTick() { //println("onTick") //increment the elapsed time by 1 second self.elapsedTime++; //Notify the implementors of the updated value of elapsed time self.handler(elapsedTime); //If the amount of elapsed time in seconds is same as the total time in seconds for which this timer was intended to run, stop the timer if self.elapsedTime == self.duration { self.stop(); } } deinit{ println("timer was invalidated from deinit()") self.timer.invalidate(); } 

}

我build议取消计时器,并在应用程序转到后台时存储NSDate 。 你可以使用这个通知来检测应用程序到后台:

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

然后取消定时器并存储date:

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

使用此通知来检测用户回来:

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

然后计算从存储date到当前date的差异,更新您的计数器并再次启动计时器:

 func startApp(){ let difference = self.currentBackgroundDate.timeIntervalSinceDate(NSDate()) self.handler(difference) //update difference self.start() //start timer } 

你不应该这样做。 正在运行的定时器会使设备的处理器全功率运行,这是不好的。

只允许某些types的应用程序从后台无限期地运行代码,例如VOIP应用程序和音乐应用程序。

几个选项:

  1. 为将来的date设置本地通知(将向您的应用发送消息,或在不再运行时重新启动它)。

  2. 当你启动计时器时,logging当前的NSDate。 然后,当您的应用程序返回到前台或重新启动时,获取将当前date与保存的date进行比较,计算出已经过去的时间量,并确定您的计时器是否已完成。

试试这个代替..这段代码更新了应用程序从后台/暂停和处于活动状态的时间..

类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 } 

}