【问题标题】:Removing scheduled local notification删除计划的本地通知
【发布时间】:2020-04-22 08:51:27
【问题描述】:

我知道有很多类似的问题和答案,我都查看了它们,但仍然找不到解决方案。尽管从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

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

  • 应用创建一些每天、每周、每月等重复的事件

  • 为每个事件创建一个通知

  • 在活动日期发送通知

  • 用户可以看到即将发生的事件并且可以选择跳过一个周期 => 这是问题所在 -> 当用户选择跳过时,我运行 func removeExisting(identifierST: String) 将其删除,但是当跳过的事件来了,通知还在发送中。

编辑 2

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

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

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

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

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

这些都不行。

【问题讨论】:

    标签: swift ios13 unusernotificationcenter


    【解决方案1】:

    首先,让我解释一下为什么你正在做的事情不起作用。

    假设您有许多不同的日期,例如: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 个通知的限制),或者像我一样为每个工作日设置七个重复通知,然后删除一次不想要的,改天再添加一次,但不是同一天,因为它会再次触发。

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

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

    【讨论】:

    • 嘿,达科他州,谢谢你看这个。请参阅编辑 2 以回应您的回答。
    • 嘿@grep,请再次检查我的答案,我完全重新编辑它以获得更清晰的解释
    • 谢谢@dakota,我已经相应地修改了我的代码,经过测试并且可以正常工作。我接受你的回答。
    【解决方案2】:

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

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

    【讨论】:

    • 请参阅更新 1 以了解更多详细信息,并回答您的问题,是的,我调用 getPendingNotificationRequests 并没有看到那里删除了一个,但是当日期到来时,它仍然被触发。
    • 感谢您的更新。您确定它没有再次错误地调用add() 吗? (在它被删除和应该触发通知之间的某个时间?)也许在调用 add() 的地方添加一些日志记录?
    • 删除后,它确实会再次添加一个新的,但触发日期不同,即如果事件是每周一的每周一次,则用户跳过 1 个周期,我删除了即将到来的星期一并创建一个新的下周一一个,但我仍然收到第一个周一的通知。这有意义吗?
    • 您使用 getPendingNotificationRequests 检查了这个新的实际上是在下周一安排的吗?
    • 是的,我可以看到新日期的新安排
    【解决方案3】:

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

    原始方法

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

    新方法

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

    【讨论】:

    • 即使使用这种新方法,我仍然看到下一个触发日期未随新日期更新,因此这不太可能起作用,也许问题在于我如何从组件设置触发日期。我会用那段代码更新问题。
    • 是的,效果是(至少应该如此)用新的信息(包括新的日期)用相同的标识符覆盖之前的通知。
    猜你喜欢
    • 1970-01-01
    • 2019-09-29
    • 2021-10-04
    • 2021-11-28
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    相关资源
    最近更新 更多