如何在后台更新 UILabel 计时器

How to update a UILabel timer after being in background

我正在尝试构建一个简单的计时器,它在活动时工作正常。问题是,如果我在还剩 30 秒时退出应用程序并在 10 秒后返回,这表明我的计时器还剩下大约 28 秒。然后最重要的是,我的通知时间变得一团糟。我一直在尝试许多不同的方法来解决问题,但都无济于事。有人可以帮忙吗?

import UIKit
import AVFoundation
import Foundation
import UserNotifications

class TimerController: UIViewController, UNUserNotificationCenterDelegate {

//MARK: - Variables and Constants

var Minutes = 10.0
var audioPlayer = AVAudioPlayer()
let vc = ViewController()
var isGrantedAccess = false
private var timer = Timer()
let timeInterval = 0.1

//MARK: - IBOutlet
@IBOutlet weak var label: UILabel!
@IBOutlet weak var sliderOutlet: UISlider!
@IBOutlet weak var startOutlet: UIButton!
@IBOutlet weak var stopOutlet: UIButton!


//MARK: - Functions

//MARK: - Notification Alert Functions

func startTimer() {

}

func stopTimer(){
    //shut down timer
    timer.invalidate()
    //clear out any pending and delivered notifications
    UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
    UNUserNotificationCenter.current().removeAllDeliveredNotifications()
}

func sendNotification() {

        let content = UNMutableNotificationContent()
        content.title = "Timer Finished"
        content.body = "Your escort should be here"
        content.sound = UNNotificationSound.default()
        content.categoryIdentifier = "timer.category"

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: Minutes, repeats: false)
        let request = UNNotificationRequest(identifier: "timer.request", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request) { (error) in
            if let error = error{
                print("Error posting notification:\(error.localizedDescription)")

        }
    }
}


func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    if response.actionIdentifier == "stop.action"{
        stopTimer()
    }
    completionHandler()
}

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert,.sound])
}




//MARK: - UIButtons
@IBAction func slider(_ sender: UISlider)
{
    Minutes = Double(sender.value)
    label.text = String(format: "%.0f", Minutes) + " Minutes"
}


@IBAction func start(_ sender: AnyObject) {

    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(counter), userInfo: nil, repeats: true)

    sliderOutlet.isHidden = true
    startOutlet.isHidden = true
    self.sendNotification()

}

func counter() {
    DispatchQueue.main.async {

    self.Minutes -= 1
    self.label.text = String(format: "%.0f", self.Minutes) + " Minutes"
    }
    if (Minutes == 0)
    {
        timer.invalidate()

        sliderOutlet.isHidden = false
        startOutlet.isHidden = false


    }
}



@IBAction func stop(_ sender: AnyObject)
{
    timer.invalidate()
    Minutes = 0
    sliderOutlet.setValue(10, animated: true)
    label.text = "0 Minutes"

    audioPlayer.stop()

    sliderOutlet.isHidden = false
    startOutlet.isHidden = false
}



override func viewDidLoad()
{
    super.viewDidLoad()

    print(vc.isGrantedAccess)

    do
    {
        let audioPath = Bundle.main.path(forResource: "1", ofType: ".mp3")
        try audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath!))
    }
    catch
    {
        //ERROR
    }

}

进入后台时将 Date() 存储在 NSUserDefaults 中

func applicationDidEnterBackground(_ application: UIApplication) {}

然后在

中进入前台时计算新日期之间的差异
func applicationWillEnterForeground(_ application: UIApplication) {}