簡體   English   中英

如何為任務設置每日本地通知,但在用戶之前完成任務時不顯示

[英]How to set up daily local notification for tasks but don't show it when user completes the task before

我知道以前出現過類似的問題,但我認為我需要更多說明,因為我仍然不知道如何完成。 我是初學者,所以請原諒我的任何錯誤。

如果用戶尚未完成,我正在嘗試從我的應用程序中獲取日常任務的每日提醒,那么當他已經完成任務時,我怎樣才能讓它不顯示呢?

到目前為止我發現的解決方案建議刪除未決通知並同時為將來的日期設置新的通知。

我使用此代碼成功設置了每日通知:

    func sendDailyReminder() {
        let content = UNMutableNotificationContent()
        content.title = "Daily reminder"
        content.body = "You still have task to complete today."
        content.sound = UNNotificationSound.default
        var dateComponents = DateComponents()
        dateComponents.hour = 20
        dateComponents.minute = 00
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
        let request = UNNotificationRequest(identifier: "dailyTrigger", content: content, trigger: trigger)

        center.add(request) { (error) in
            if let error = error {
                print("Notification Error: ", error)
            }
        }
    }

我也可以使用 removePendingNotificationRequest 方法成功刪除掛起的通知,但是我如何在這里使用 dateComponents 為明天設置觸發器?

或者還有其他方法可以實現嗎? 也許在發送通知之前使用后台獲取來檢查它是否完成?

我發現一些回復表明這實際上是不可能的,但是任何任務或待辦應用程序如何才能實現這樣的目標呢?

我最終在每個工作日使用多個通知,但設置方式略有不同:

首先使用 weekday Int 作為標識符設置每日提醒

func setWeekdayReminder(weekday: Int) {
        let center = UNUserNotificationCenter.current()
        let content = UNMutableNotificationContent()
        content.title = "Daily reminder"
        content.body = "You still have some tasks to complete today."
        content.sound = UNNotificationSound.default
        var dateComponents = DateComponents()
        dateComponents.hour = 18
        dateComponents.minute = 35
        dateComponents.weekday = weekday
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true
        let request = UNNotificationRequest(identifier: String(weekday), content: content, trigger: trigger)

        center.add(request) { (error) in
            if let error = error {
                print("Notification Error: ", error)
            }
        }
    }

然后我做了一個 function 來檢查用戶啟動應用程序后是否缺少任何一天(今天除外,所以即使在用戶完成任務時提前刪除它,我也不會再次請求今天的通知)

func checkDailyReminder() {

       let currentWeekday = Calendar.current.component(.weekday, from: Date())

       center.getPendingNotificationRequests { (requests) in
            var weekdayArray : [Int] = []

            for each in requests {
               weekdayArray.append(Int(each.identifier)!)
            }
            for number in 1...7 {
                if weekdayArray.contains(number) {
                    print("weekdayArray contains weekday \(number)")
                } else {
                    print("weekdayArray doesnt contain weekday \(number)")
                    if number != currentWeekday {
                          self.setWeekdayReminder(weekday: number)
                    }
                }
            }

        }
    }

當然,這是一種黑客行為,當用戶完成任務並且以某種方式不會 go 回來一周並在同一個工作日再次打開它時,他那天不會收到通知,但它適用於當時的 rest。

這是我想出的。 基本上每天應用程序運行,我都會運行這個 function 來設置本地通知。 它為接下來的 14 天設置了它們。 它每天運行,它總是會在從現在開始的第 14 天設置。 它會跳過其他人,他們已經待定。 今天還有一個function取消通知,一旦任務完成。

func setupLocalNotifications() {
    let center = UNUserNotificationCenter.current()
    center.getNotificationSettings { setting in
        guard setting.authorizationStatus == .authorized else {
            print("Not authorized for local push notifications")
            return
        }
        
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyyMMdd"
        dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
        
        let calendar = Calendar.current
        var date = calendar.date(bySettingHour: 14, minute: 0, second: 0, of: Date())!
        center.getPendingNotificationRequests { [weak self] notificationRequests in
            (1...14).forEach { _ in
                //Capture this date.
                let thisDate = date
                
                //Prepare the next date.
                date = calendar.date(byAdding: .day, value: 1, to: date)!
                
                let identifier = dateFormatter.string(from: thisDate)
                
                guard thisDate.isPastDate == false else {
                    Log.d(TAG, "Task Date is in the past - Skipping \(identifier)")
                    return
                }
                
                // Check if we've already scheduled this identifier
                guard notificationRequests.first(where: { $0.identifier == identifier }) == nil else {
                    print("Task Already Scheduled - Skipping \(identifier)")
                    return
                }
                
                // Check if we'e already done our task for the day.
                /*
                 TODO: Special Code Guard that checks if we've already completed the task today. (I took this out because it had project specific code, but you should check your core data or whatever, to see if the task is finished for today.
                 */
                
                let content = UNMutableNotificationContent()
                
                content.title = "Title"
                content.body = "Body"
                
                let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: thisDate)
                
                let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
                
                let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
                
                let notificationCenter = UNUserNotificationCenter.current()
                notificationCenter.add(request) { (error) in
                    if error != nil {
                        Log.e(TAG, error)
                    }
                    print("Successfully scheduled: \(identifier)")
                }
            }
        }
    }
}

這是取消任務 function。

func cancelTodaysNotification() {
    let center = UNUserNotificationCenter.current()
    let calendar = Calendar.current
    let dateFrom = calendar.startOfDay(for: Date())
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyyMMdd"
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    
    let identifier = dateFormatter.string(from: dateFrom)

    center.removePendingNotificationRequests(withIdentifiers: [identifier])
    
    print("Removed Local Notification for Date: \(identifier)")
    
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM