如何使用 Date() 函数和应用程序在前台和后台时的时间戳来获取经过的时间?

How can I use the Date() function and time stamps from when the app is in the foreground and background to get elapsed time?

我正在考虑使用 DataFormatter.localizedString... 并将该值设置为 2 个不同的变量,一个用于应用程序离开前台和应用程序返回前台的时间,然后将它们减去获取已用时间以将其设置为 breakSession.text...但我对 swift 有点陌生,不清楚如何使用 Date() 函数。我的主要目标是让 breakTimer 在应用程序处于后台时为 运行ning,而在应用程序处于前台时暂停,但用户仍应能够看到经过的时间。但显然,计时器不能在后台 运行...有人可以帮忙吗?

import UIKit

class HomeViewController: UIViewController {

@IBOutlet weak var focusSession: UILabel!
@IBOutlet weak var breakSession: UILabel!

/** Focus Time **/

var prodMinutes = String() // Productive time data from ViewController.swift arrives and is stored
lazy var intProdSeconds = (60*Int(prodMinutes)!) + 1
var focusTimer = Timer()
var isFocusTimerRunning = false // Make sure only one timer is running at a time

/** Break Time **/

var breakMinutes = String() // Break time data from BreaTimeViewController.swift arrives and is stored
lazy var intBrSeconds = (60*Int(breakMinutes)!) + 1
var breakTimer = Timer()
var isBreakTimerRunning = false

override func viewDidLoad() {
    super.viewDidLoad()

    let state: UIApplicationState = UIApplication.shared.applicationState

    /** Focus Time **/

    if isFocusTimerRunning == false && state == .active {
        runProdTimer()

    }
    else {
        focusTimer.invalidate()
    }

    /** Break Time (This part doesn't work) 

    if isBreakTimerRunning == false && state == .background {
        runBrTimer()
    }
    else {
        breakTimer.invalidate()
    } **/
}

func runProdTimer() {
    focusTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(HomeViewController.updateProdTimer)), userInfo: nil, repeats: true)
    isFocusTimerRunning = true
}

func runBrTimer() {
    breakTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(HomeViewController.updateBrTimer)), userInfo: nil, repeats: true)
    isBreakTimerRunning = true
}

@objc func updateProdTimer() {

    if intProdSeconds < 1 {
        focusTimer.invalidate()
        focusSession.text = "00:00"
    }
    else {
        intProdSeconds -= 1
        focusSession.text = prodTimeString(fTime: TimeInterval(intProdSeconds))
    }

}



@objc func updateBrTimer() {

    if intBrSeconds < 1 {
        breakTimer.invalidate()
        breakSession.text = "00:00"
    }

    else {
        intBrSeconds -= 1
        breakSession.text = brTimeString(bTime: TimeInterval(intBrSeconds))
    }

}

func prodTimeString(fTime: TimeInterval) -> String {

    let prodMinutes = Int(fTime) / 60 % 60
    let prodSeconds = Int(fTime) % 60

    return String(format: "%02d:%02d", prodMinutes, prodSeconds)

}

func brTimeString(bTime: TimeInterval) -> String {

    let brMinutes = Int(bTime) / 60 % 60
    let brSeconds = Int(bTime) % 60

    return String(format: "%02d:%02d", brMinutes, brSeconds)
}

更新:好的,下面 Sunil Chauhan 的回答有点奏效了。我能够得到时间戳和东西。但是,我 运行 遇到了另一个问题,我不明白为什么..

@objc func appWillEnterForeground() {
    endDate = Date()
    let secondsPassedInBackground = endDate.timeIntervalSince(beginDate)
    print(secondsPassedInBackground)
    let updateBrTime = intBrSeconds - Int(secondsPassedInBackground) // Updated Break Time after user returns to the app aka foreground
    breakSession.text = brTimeString(bTime: TimeInterval(updateBrTime))
}

在这个函数中,我基本上是想把经过的时间从 intBrSeconds 中减去它,这就像用户为自己设置的 "Break" 时间。因此,从本质上讲,当用户离开应用程序时,它作为 "Break Timer" 运行 的计时器。标签首先会正确更新,并根据经过的时间正确减去正确的秒数。然而,在经过的时间超过大约 30 秒左右之后,计时器开始增加。所以就像它被设置为 10:00.. 它会下降说,9:34 但是下次你离开应用程序在后台并回来时,它会说 9:55或大于 9:34 的东西,这是不应该发生的。我该如何解决这个问题?

试试这个:

var beginDate = Date()
var endDate = Date()

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(appWentInBackground), name: .UIApplicationDidEnterBackground, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: .UIApplicationWillEnterForeground, object: nil)
}

@objc
func appWentInBackground() {
    beginDate = Date()
}

@objc
func appWillEnterForeground() {
    endDate = Date()
    let secondsPassedInBackground = endDate.timeIntervalSince(beginDate)
    //  secondsPassedInBackground passed while app was in background.
}