应用程序在后台运行/暂停

时间:2015-08-06 17:42:34

标签: ios swift nstimer background-process countdown

我有一个功能倒数计时器。

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

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

以下是我的计时器的代码:

    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();
}

}

4 个答案:

答案 0 :(得分:6)

我建议取消计时器并在应用程序进入后台时存储int compare (int[] first, int[] second)。 您可以使用此通知来检测应用程序转到后台:

NSDate

然后取消计时器并存储日期:

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

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

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

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

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

答案 1 :(得分:3)

你不应该这样做。正在运行的计时器可使设备的处理器以全功率运行,这很糟糕。

只允许某些类型的应用从后台无限期地实际运行代码,例如VOIP应用和音乐应用。

有两种选择:

  1. 设置未来日期的本地通知(将向您的应用发送消息,或者如果不再运行则重新启动它。)

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

答案 2 :(得分:0)

请尝试使用此代码..此代码会更新应用从后台/暂停状态恢复并处于活动状态的时间。

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
}

}

答案 3 :(得分:0)

确保打开背景模式并在xCode中设置所需的值。这很奇怪,但是即使关闭了后台模式,此代码也可以工作。在AppDelegate中设置application.beginBackgroundTask {}后,任何计时器似乎都可以正常工作。

我使用以下代码:

在AppDelegate中添加以下代码:

func applicationDidEnterBackground(_ application: UIApplication) {

    application.beginBackgroundTask {} // allows to run background tasks
}

然后在所需的位置调用方法。

func registerBackgroundTask() {
    DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime.now() + 5, qos: .background) {
            print("fasdf")
        }
}