I am trying to build a simple timer which works just fine when it is active. The problem is, If I quit out of the application at 30 seconds left and come back 10 seconds later, it shows that I have roughly 28 seconds left on my timer. Then on top of that, my notification timing gets messed up. I've been trying many different ways to solve the problem but to no avail. Can anyone help with this?
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
}
}
Store Date() in NSUserDefaults when you go to background in
func applicationDidEnterBackground(_ application: UIApplication) {}
then calculate difference between new Date when you go to foreground in
func applicationWillEnterForeground(_ application: UIApplication) {}