删除预定的本地通知

Removing scheduled local notification

我知道有很多类似的问题和答案,我都看了一遍,但还是找不到解决办法。尽管从 UNUserNotificationCenter 中删除了预定的通知,它仍然会被触发。

我创建本地通知如下:

let aDF = DateFormatter()
aDF.dateFormat = "yyyy-MM-dd HH:mm:ss"
var identifierST = ""
    if update == true {
        identifierST = myCoreDataEntity.notificationUID!
    } else {
        identifierST = aDF.string(from: Date())
    }

let notif = UNMutableNotificationContent()
notif.title = "some string"
notif.body = "some string"
var dateComp: DateComponents
switch myCoreDataEntity.schedule {
case 1: //daily
    dateComp = Calendar.current.dateComponents([.hour, .minute], from: myCoreDataEntity.date)

case 2: //weekly
    dateComp = Calendar.current.dateComponents([.weekday, .hour, .minute], from: myCoreDataEntity.date)

case 3: //monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

case 4: //quartely - this is actually not quarterly, dont know how to set quarterly, setting monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

case 5: //halfyearly - this is actually not halfyearly, dont know how to set halfyearly, setting monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

case 6: //yearly
    dateComp = Calendar.current.dateComponents([.month, .day, .hour, .minute], from: myCoreDataEntity.date)

default: //monthly
    dateComp = Calendar.current.dateComponents([.day, .hour, .minute], from: myCoreDataEntity.date)

}
dateComp.hour = 10
dateComp.minute = 0

let notificationTrigger = UNCalendarNotificationTrigger(dateMatching: dateComp, repeats: true)
        let request = UNNotificationRequest.init(identifier: timeStampST, content: notif, trigger: notificationTrigger)
        UNUserNotificationCenter.current().add(request) { (error) in
            if (error != nil) {
                 print (error) //notify user that reminder was not saved
            } else {
                 myCoreDataEntity.notificationUID = identifierST
            }
        }

notificationUID 是 CoreData 实体上的一个字符串属性,我在其中存储创建的通知标识符,因此我可以稍后检索它。

以上工作正常,通知已安排并在定义的日期和时间发送,所以这里没问题。

每当我需要删除特定通知时,我都会检索保存的通知标识符 (notificationUID) 并将其传递给以下函数:

func removeExisting(identifierST: String) {
     UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifierST])
}

在尝试查找问题时,我检索了所有未决通知并将它们的 identifiers 与我传递给 removePendingNotificationRequestsidentifierST 进行了比较,它们匹配

UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { requests in
        for request in requests {
            print("==============================================")
            print(request.identifier)
            print(request.content.title)
            print(request.content.subtitle)
            print(request.content.body)
        }
})

但是那些被取消的通知仍然被触发,我是不是漏掉了一些明显的东西?

编辑 1

提供有关应用程序逻辑和场景的更多详细信息:

编辑 2

回复:关于删除通知时可能出现的拼写错误或逻辑错误的要点 - 我确定那里没有错误的原因是因为当我没有跳过或编辑事件时它有效,但我正在删除它,即假设事件日期是明天,通知定于明天 10:00 发送。今天用户决定他根本不想要这个并删除它,所以我 运行 func removeExisting(identifierST: String) 并且它有效 - > 明天不会生成该事件的通知。

但是,如果用户决定不完全删除,而只是跳过明天的 1 天,并在后天继续(如果日程安排是每天),这就是我遇到的问题。我试图通过 3 种方法解决这种情况:

方法 1 - 删除现有通知并创建一个具有新标识符和新触发日期的新通知 - 后天

方法 2 - 创建具有相同标识符的通知(假设这不会创建新的但会修改现有的)但新的触发日期 - 后天

方法 3 - 删除现有通知并创建一个具有相同标识符和新触发日期的新通知 - 后天

None 本作品。

你的意思是,你调用了 getPendingNotificationRequests 并且不再看到你删除的那个?那么,您确定之后添加的代码不会被意外调用吗? (所以它可以再次添加?)

UNUserNotificationCenter.current().add()的一个特点是,如果已经安排了一个需要ID的通知,则不会同时安排另一个通知,但也不会报错。你可以认为它覆盖了现有的。因此,如果您的代码以某种方式一次又一次地安排相同的通知,您可能不会注意到。直到您尝试删除通知,然后它们才会重新安排。

我现在再次观看了相关的 WWDC 视频 - https://developer.apple.com/videos/play/wwdc2016/707 - 并稍微改变了逻辑。

原方法

当用户跳过一个周期时,我将删除预定的通知并创建一个新的通知,其中包含新的标识符和新的触发日期。

新方法

当用户跳过一个周期时,我不会删除任何内容,而是创建一个 "new" 通知,其中包含新的触发日期,但使用相同的标识符。正如我从视频中了解到的那样,使用相同的标识符实际上并不是在创建新通知,而是在更新现有通知。我将能够在 24 小时内确认这是否有效。

首先,让我解释一下为什么您所做的不起作用。

假设您有许多不同的日期,例如:4 月 27 日、5 月 4 日、5 月 11 日、5 月 18 日等。

您正在将 dateComp 指定为

dateComp = Calendar.current.dateComponents([.weekday, .hour, .minute], from: myCoreDataEntity.date)

因此,对于上述每个日期,您的 dateComp 将如下所示:

dateComp = [Monday, 10, 30] // April 27th
dateComp = [Monday, 10, 30] // May 4th
dateComp = [Monday, 10, 30] // May 11th
dateComp = [Monday, 10, 30] // May 18th

然后你将那个 dateComp 放入你的触发器中,你看到我要用它做什么了吗?除了这三个参数之外,触发器与您的日期没有任何关系,通过在一周后更改日期,您实际上使用的是完全相同的触发器。

当您将请求添加到通知中心时,您的通知将设置为在下一个可用的星期一 10:30 显示,而不是在您的日期星期一 10:30。

我遇到了同样的问题并在这里发布了类似的问题。从我所有的研究和其他人所说的,不可能在当前的 UNNotificationCenter 中设置从特定的未来日期重复通知,如果有人能证明我错了,我会非常高兴。

您可以根据您的日期设置整个 dateComp,例如 [.month, .day, .hour, .minute],但是如果您将 repeat 设置为 true,它将仅在相同的 [.month, . day, .hour, .minute] 每年都会重复。

解决方案可以是为每个特定日期设置非重复通知(同一时间最多可以有 64 个通知),或者像我的情况一样为每个工作日设置七个重复通知,然后只需一次删除您不想要的那个,改天再添加一次,但不是同一天,因为它会再次触发。

您可以在此处查看我在我的应用程序中使用的代码: