如何为任务设置每日本地通知,但在用户之前完成任务时不显示
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)
}
}
}
然后我做了一个功能来检查用户启动应用程序后是否有任何遗漏的日期(今天除外,所以即使在用户完成任务时提前删除它,我也不会再次请求今天的通知)
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)
}
}
}
}
}
当然这是一种 hack,当用户完成任务并且不知何故一周内不会返回并在同一工作日再次打开它时,他当天不会收到通知,但它可以休息当时。
这是我想到的。基本上每天应用 运行s,我都会 运行 这个功能,来设置本地通知。它为接下来的 14 天设置了它们。每天它 运行s,它总是会从现在开始设置第 14 天。它会跳过其他人,他们已经待定。还有今天任务完成后取消通知的功能
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: { [=10=].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)")
}
}
}
}
}
这里是取消任务函数。
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)")
}
我知道以前出现过类似的问题,但我认为我需要更多说明,因为我仍然不知道如何完成。我是一名初学者,所以请原谅我的错误。
如果用户尚未完成日常任务,我正在尝试从我的应用程序中获得每日提醒,那么我怎样才能让它在他已经完成任务时不显示?
目前我找到的解决方案建议删除未决通知并同时为未来日期设置新通知。
我使用此代码成功设置了每日通知:
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)
}
}
}
然后我做了一个功能来检查用户启动应用程序后是否有任何遗漏的日期(今天除外,所以即使在用户完成任务时提前删除它,我也不会再次请求今天的通知)
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)
}
}
}
}
}
当然这是一种 hack,当用户完成任务并且不知何故一周内不会返回并在同一工作日再次打开它时,他当天不会收到通知,但它可以休息当时。
这是我想到的。基本上每天应用 运行s,我都会 运行 这个功能,来设置本地通知。它为接下来的 14 天设置了它们。每天它 运行s,它总是会从现在开始设置第 14 天。它会跳过其他人,他们已经待定。还有今天任务完成后取消通知的功能
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: { [=10=].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)")
}
}
}
}
}
这里是取消任务函数。
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)")
}