CKQueryNotification.recordID:无法识别的选择器发送到实例

Posted

技术标签:

【中文标题】CKQueryNotification.recordID:无法识别的选择器发送到实例【英文标题】:CKQueryNotification.recordID: unrecognized selector sent to instance 【发布时间】:2019-12-22 20:58:31 【问题描述】:

我正在尝试设置静默推送通知以使用 CloudKit 跨设备传播本地通知,但我无法理解为什么每次收到远程通知时我的应用程序都会崩溃。

在我尝试处理收到的通知之前,一切正常。尝试访问 didReceiveRemoteNotification 中的 CKQueryNotification 对象的 recordID 时发生崩溃。

我正在应用程序 didFinishLaunchingWithOptions 中注册远程通知。这是剩下的代码:

在 didRegisterForRemoteNotification 中,我正在为记录类型 CD_Task 创建一个 CKSubscription。

   func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 

        let subscription = CKQuerySubscription(recordType: "CD_Task", predicate: NSPredicate(format: "TRUEPREDICATE"), options: .firesOnRecordCreation)

        let info = CKSubscription.NotificationInfo()            
        subscription.notificationInfo = info

        CKContainer.default().privateCloudDatabase.save(subscription, completionHandler:  subscription, error in
            if error == nil 
                // Subscription saved successfully
             else 
                // Error occurred, handle it
            
        )
    

在 DidReceiveRemoteNotification 中,我将一个 CKQueryNotification 对象传递给一个函数来处理从 iCloud 接收到的远程通知:

   func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
        if let ckqn = CKQueryNotification(fromRemoteNotificationDictionary: userInfo as! [String:NSObject]) 
            self.iCloudHandleNotification(ckqn)
        
    

最后是iCloudHandleNotification函数代码:

        func iCloudHandleNotification(_ ckqn: CKQueryNotification) 
                    switch ckqn.queryNotificationReason 
                    case .recordCreated:
                        // This is where it crashes.. when I try to access ckqn.recordID
                        CKContainer.default().privateCloudDatabase.fetch(withRecordID: ckqn.recordID!)  (record, error) in
                            if let record = record 
                                // Handle creating local notif for record
                             else if let error = error 
                                print("Unable to retrieve record: \(error)")
                            
                        
                    default:
                        break
                 
        

编辑:

经过调查,似乎我得到的是 CKDatabaseNotification 而不是 CKQueryNotification -- 我应该如何指定我想要 CKQueryNotification?

【问题讨论】:

【参考方案1】:

我终于明白了。我正在使用 NSPersistentCloudKitContainer 跨设备同步我的数据。我的订阅正在观察对 NSPersistentCloudKitContainer 创建的记录所做的任何更改,因此每次进行更改时它都会创建 CKDatabaseNotification,而不是 CKQueryNotification。由于我试图处理 CKQueryNotification,我的应用程序不断崩溃,因为它找不到记录 ID,因此出现错误消息。

为了解决这个问题,我最终在 iCloud 中创建了一个单独的记录(不是 NSPersistentCloudKitContainer 的一部分),并让我的 CKSubscription 观察对该记录的任何更改。

【讨论】:

以上是关于CKQueryNotification.recordID:无法识别的选择器发送到实例的主要内容,如果未能解决你的问题,请参考以下文章