首页 文章

在iOS 10中安排和处理本地通知

提问于
浏览
0

我一直致力于我的一个项目,我允许用户在他们想要的时间安排多个通知 .

iOS 10让我们能够使用DateComponents作为我们通知的开火日期,但我对于如何安排和处理多个通知感到很遗憾 .

每个通知都需要自己的请求,然后需要自己的标识符,否则您无法创建多个通知 .

我想我必须使用标识符来安排和处理通知,但现在我的代码是如此混乱,我一直认真地问自己,如果没有更简单的方法这样做 .

根据我的数据模型,通知唯一标识符包括:

  • 我的模特的ID

  • 每次创建新通知时递增的数字

  • 上面用下划线分隔

因此,例如,如果我必须为id为3的对象安排10个通知,它将如下所示: 3_1, 3_2, 3_3...

每次收到通知时,我都会通过收到的通知循环来更新我的UI . 当用户希望删除所接收的特定型号的通知时,我通过检查以相同ID开头的标识符来遍历所接收的通知的唯一标识符 .

我真的没有看到我如何能够做到这一点,否则因为根据文档,删除已发送通知的唯一方法是使用标识符: UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers:)

问题是,它创造了各种各样的问题,虽然我可以很容易地纠正它们,但它看起来非常hacky . 我并不为自己所做的事感到自豪,我正在寻找更聪明的方法来解决这个问题 . 我故意没有发布任何代码,因为这不是问题 . 这种方法是真正的问题 .

我在这里问,因为 UserNotifications 框架很新,我无法找到关于这个主题的资源 .

任何的想法 ?提前致谢 .

编辑:这是一些代码 .

@available(iOS 10.0, *)
    func checkDeliveredAndPendingNotifications(completionHandler: @escaping (_ identifierDictionary: Dictionary<String, Int>) -> ()) {

        var identifierDictionary:[String: Int] = [:]
        UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in

            for notification in notifications {
                let identifierArraySplit = notification.request.identifier.components(separatedBy: "_")
                if identifierDictionary[identifierArraySplit[0]] == nil || identifierDictionary[identifierArraySplit[0]]! < Int(identifierArraySplit[1])!  {
                    identifierDictionary[identifierArraySplit[0]] = Int(identifierArraySplit[1])
                }
            }

            UNUserNotificationCenter.current().getPendingNotificationRequests(completionHandler: { (requests) in
                for request in requests {
                    let identifierArraySplit = request.identifier.components(separatedBy: "_")
                    if identifierDictionary[identifierArraySplit[0]] == nil || Int(identifierArraySplit[1])! > identifierDictionary[identifierArraySplit[0]]!  {
                        identifierDictionary[identifierArraySplit[0]] = Int(identifierArraySplit[1])
                    }
                }
                completionHandler(identifierDictionary)
            })
        }
    }


@available(iOS 10.0, *) 
    func generateNotifications() {
        for medecine in medecines {
            self.checkDeliveredAndPendingNotifications(completionHandler: { (identifierDictionary) in
                DispatchQueue.main.async {
                    self.createNotification(medecineName: medecine.name, medecineId: medecine.id, identifierDictionary: identifierDictionary)
                    }                    
            })
        }
    }


@available(iOS 10.0, *)
    func createNotification(medecineName: String, medecineId: Int identifierDictionary: Dictionary<String, Int>) {

        let takeMedecineAction = UNNotificationAction(identifier: "TAKE", title: "Take your medecine", options: [.destructive])
        let category = UNNotificationCategory(identifier: "message", actions: [takeMedecineAction], intentIdentifiers:[], options: [])
        UNUserNotificationCenter.current().setNotificationCategories([category])

        let takeMedecineContent = UNMutableNotificationContent()
        takeMedecineContent.userInfo = ["id": medecineId]
        takeMedecineContent.categoryIdentifier = "message"
        takeMedecineContent.title = medecineName
        takeMedecineContent.body = "It's time for your medecine"
        takeMedecineContent.badge = 1
        takeMedecineContent.sound = UNNotificationSound.default()

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: false)

        var takeMedecineIdentifier = ""
        for identifier in identifierDictionary {
            if Int(identifier.key) == medecineId {
                let nextIdentifierValue = identifier.value + 1
                takeMedecineIdentifier = String(medecineId) + "_" + String(nextIdentifierValue)
            }
        }
        let takeMedecineRequest = UNNotificationRequest(identifier: takeMedecineIdentifier, content: takeMedecineContent, trigger: trigger)

        UNUserNotificationCenter.current().add(takeMedecineRequest, withCompletionHandler: { (error) in
            if let _ = error {
                print("There was an error : \(error)")
            }
        })
    }

checkDeliveredAndPendingNotifications 方法中,我遍历所有挂起和传递的通知,因此稍后我可以创建一个不存在的标识符 . 我还没有找到另一种方法来为每个通知生成唯一标识符 .

由于大多数工作是在另一个异步队列上完成的,所以我在完成工作后也创建了一个完成处理程序 . 然后我在主线程上调用 createNotification 方法(因为我也不得不这样做),这应该创建一个通知 .

这里的问题是 func add(UNNotificationRequest, withCompletionHandler: (Error?) -> Void)? = nil) 方法,它也是异步工作 . 所以当我在 generateNotifications 回到我的循环时, checkDeliveredAndPendingNotifications 返回不正确的数据 . 好吧不是不正确它's just that the notification hasn' t已经创建了......

我是一个穿线程的总菜鸟,我一直坚持这种操作,我不知道该往哪里去 . 我不确定我是否以正确的方式解决问题 .

1 回答

相关问题