Reputation:
If the start button is pressed my notification will go continue to go off every 30 seconds infititley. I want to make it so that every time the user hits the start button the countdown is reset and the notification will only appear in the 30 seconds after the start button is pressed. So if the user hits the start button before the 30 seconds are up for a infinite amount of times the user will never see the notification.
import UIKit
import UserNotifications
class ViewController: UIViewController,UNUserNotificationCenterDelegate {
var isGrantedAccess = false
private var timer = Timer()
func startTimer(){
let timeInterval = 30.0
if isGrantedAccess && !timer.isValid { //allowed notification and timer off
timer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true, block: { (timer) in
self.sendNotification()
})}}
func stopTimer(){
//shut down timer
timer.invalidate()
//clear out any pending and delivered notifications
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
}
func sendNotification(){
if isGrantedAccess{
let content = UNMutableNotificationContent()
content.title = "HIIT Timer"
content.body = "30 Seconds Elapsed"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "timer.category"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.001, 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)")
}}}}
@IBAction func startButton(_ sender: UIButton) {
startTimer()
}
func timeString(time:TimeInterval) -> String {
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format: " %02i : %02i", minutes, seconds)
}
override func viewDidLoad() {
super.viewDidLoad()
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound]) { (granted, error) in
self.isGrantedAccess = granted
}
let stopAction = UNNotificationAction(identifier: "stop.action", title: "Stop", options: [])
let timerCategory = UNNotificationCategory(identifier: "timer.category", actions: [stopAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([timerCategory])
}
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])
}}
Upvotes: 0
Views: 672
Reputation: 19156
You just need to invalidate the timer and schedule it again. Try this.
func startTimer(){
stopTimer()
let timeInterval = 30.0
if isGrantedAccess { //allowed notification and timer off
timer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true, block: { (timer) in
self.sendNotification()
})
}
}
Upvotes: 0