繁体   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