如何接收有关与我共享的记录所做更改的cloudkit通知?

Bar*_*zyk 12 push-notification ios swift cloudkit

我在两个不同的设备上有两个icloud帐户(AB).从他们中的一个(A)我分享ckrecord到另一个(B)像这样:

let controller = UICloudSharingController { controller, preparationCompletionHandler in

    let share = CKShare(rootRecord: record)
    share[CKShareTitleKey] = "title" as CKRecordValue

    share[CKShareTypeKey] = "pl.blueworld.fieldservice" as CKRecordValue
    share.publicPermission = .readWrite

    let modifyOperation = CKModifyRecordsOperation(recordsToSave: [record, share], recordIDsToDelete: nil)
    modifyOperation.savePolicy = .ifServerRecordUnchanged
    modifyOperation.perRecordCompletionBlock = { record, error in
        print(error?.localizedDescription ?? "")
    }

    modifyOperation.modifyRecordsCompletionBlock = { records, recordIds, error in

        print(share.url)
        preparationCompletionHandler(share, CloudAssistant.shared.container, error)
    }

    CloudAssistant.shared.container.privateCloudDatabase.add(modifyOperation)
}

controller.delegate = self

UIViewController.top()?.present(controller, animated: true)
Run Code Online (Sandbox Code Playgroud)

当第二个设备(B)接受cloudkit共享时,我获取记录并订阅更改:

func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {

    let acceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
    acceptSharesOperation.perShareCompletionBlock = { metadata, share, error in

        if let error = error {
            UIAlertController.show(withMessage: error.localizedDescription)
        } else {

            let operation = CKFetchRecordsOperation(recordIDs: [cloudKitShareMetadata.rootRecordID])
            operation.perRecordCompletionBlock = { record, _, error in

                if let error = error {
                    UIAlertController.show(withMessage: error.localizedDescription)
                } else if let record = record {
                    CloudAssistant.shared.save(records: [record], recordIDsToDelete: [])

                    let options: CKQuerySubscriptionOptions = [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion]
                    let territorySubscription = CKQuerySubscription(recordType: "Territory", predicate: NSPredicate(value: true), options: options)

                    let notificationInfo = CKNotificationInfo()
                    notificationInfo.shouldBadge = false
                    notificationInfo.shouldSendContentAvailable = true

                    territorySubscription.notificationInfo = notificationInfo

                    CloudAssistant.shared.sharedDatabase?.save(territorySubscription) { _, _ in }
                }
            }

            CloudAssistant.shared.container.sharedCloudDatabase.add(operation)
        }
    }
    acceptSharesOperation.qualityOfService = .userInteractive
    CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptSharesOperation)
}
Run Code Online (Sandbox Code Playgroud)

现在,从设备一个成功地(我知道这一点,改变保存在iCloud中)在与其他人共享的记录进行更新.但设备B不知道这一点,除非我再次手动获取记录.

但从另一方面来说,它的效果非常好.

如果我在与我共享的记录上成功执行更新(在设备B上),那么设备A会获得有关更改的通知,一切都很好.有什么区别?

如何订阅与我共享的记录的更改?

PS,当我能够,我将为那些能帮助我的人开始200或更多.

iOS 11,Swift 4,Xcode 9

Thu*_*unk 2

这是我的调试清单,用于调试未按预期显示的订阅通知。听起来您可能已经排除了其中一些。

  1. 确保应用程序已注册通知
  2. 确保设备上为此应用程序启用了通知
  3. 确保所有设备都使用同一个容器
  4. 在下一次应用程序启动时,使用fetchAllSubscriptionsWithCompletionHandlerNSLog 读取所有订阅并记录每个子的详细信息(特别是:订阅 ID、触发器选项、记录类型和谓词)。验证预期的子程序是否存在。验证每个子谓词是否符合预期(在本例中,比较您在两个设备上找到的谓词)。

在以下情况下,我浪费了很多时间来调试“丢失”的通知:

  1. 我的本地构建版本使用 TEST 环境,而 TestFlight 用户正在访问 PROD 环境。调试第2步发现了这一点。
  2. 当无意中重复使用订阅 ID 时,每个新的子都会覆盖前一个。调试第4步最终发现了问题

到目前为止,这四个调试步骤已经帮助我理解了所有“缺少通知”的问题。一旦我理解了为什么没有出现通知,就缩小了负责的代码块的范围。