user8105388
user8105388

Reputation:

how to delay/debounce notification on timer (swift3)

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

Answers (1)

Bilal
Bilal

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

Related Questions