CloudKit - 如何共享多条记录和检索共享记录?

CloudKit - How to share multiple records and retrieve shared records?

我看了最后 WWDC 2016 What's New with CloudKit 以了解如何使用 CKShare

与其他用户共享记录

单条记录分享:

我能够共享和检索单个记录

即,如果 xyz@gmail.com 已创建一条记录并将其共享到 abc@gmail.com

多条记录共享:

假设有 10 条记录,xyz@gmail.com 想分享给 abc@gmail.com .当用户 xyz@gmail.com 向用户 abc@gmail.com [=14= 共享多条记录时,我遇到了这个问题]

目前我尝试过的:

首先我创建了3条笔记记录:

备注1

注2(设置parent为注1)

注3(设置parent为注1)

我用以下代码分享了 Note1(Parent 记录):

CODE - 分享记录

let controller = UICloudSharingController { controller,
        preparationCompletionHandler in

        let share = CKShare(rootRecord: self.parentRecord!)
        share[CKShareTitleKey] = "note" as CKRecordValue
        share.publicPermission = .readOnly

        let operation = CKModifyRecordsOperation(
              recordsToSave: [self.parentRecord!, share],
              recordIDsToDelete: nil)

        operation.perRecordCompletionBlock = { (record, error) in
            if let error = error {
                print("CloudKit error: \(error.localizedDescription)")
            }
        }

        operation.modifyRecordsCompletionBlock = { records, recordIDs, error in

            if error != nil {
                print(error?.localizedDescription ?? "Error")
            } else{
                print("Success")
                preparationCompletionHandler(share,CKContainer.default(), error)
            }
        }

        CKContainer.default().privateCloudDatabase.add(operation)

    }

    controller.availablePermissions = [.allowPrivate, .allowReadOnly]
    controller.delegate = self
    present(controller, animated: true)

并使用以下代码检索 shared-note:

CODE - 从 shared-note

读取数据
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {
    let acceptSharesOperation = CKAcceptSharesOperation(
        shareMetadatas: [cloudKitShareMetadata])

    acceptSharesOperation.perShareCompletionBlock = {
        metadata, share, error in
        if error != nil {
            print(error?.localizedDescription)
        } else {

            let operation = CKFetchRecordsOperation(
                recordIDs: [cloudKitShareMetadata.rootRecordID])

            operation.perRecordCompletionBlock = { record, _, error in

                if error != nil {
                    print(error?.localizedDescription)
                }

                if let shareRecord = record {
                    DispatchQueue.main.async() {
                        // Shared record successfully fetched. Update user
                        // interface here to present to user.
                        print("\(shareRecord["id"]!)") // id of note
                        print("\(shareRecord["text"])") // text of note
                        print("Shared record successfully fetched")
                    }
                }
            }

            operation.fetchRecordsCompletionBlock = { (recordsWithRecordIDs,error) in
                if error != nil {
                    print(error?.localizedDescription)
                }else {
                    if let recordsWithRecordIDs = recordsWithRecordIDs {
                        print("Count \(recordsWithRecordIDs.count)")
                    }
                }
            }
            CKContainer.default().sharedCloudDatabase.add(operation)
        }
    }

    CKContainer(identifier: cloudKitShareMetadata.containerIdentifier)
        .add(acceptSharesOperation)
}

以上方法仅提供 parent 注释数据(仅 root/parent )

查询:

1) 如何获取其他children条笔记记录? (为了便于理解,我使用了术语 children)

2)是否需要每次检查是否有新的共享记录

因为我还没有找到任何好的教程和苹果官方文档的来源。你会建议我共享和检索多条记录的方法吗?

提前致谢..!

关于问题 1,要查找引用父项的记录,您需要创建一个查询来检查 rootRecordID 的引用字段。 Apple 的这个页面有一个部分讨论了带有代码示例的检索选项。

https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/CloudKitQuickStart/AddingReferences/AddingReferences.html

关于问题 2,您可以不断轮询服务器以获取更新的记录,但 Apple 在其中一个 WWDC 视频中不鼓励这样做,因为它会产生大量网络流量(因此会耗尽您的每月配额)。我建议在 CKshare 上加一个订阅通知。这样,当您需要获取记录时,您会收到通知。

我认为 Thunk 的回答是不正确的,因为您不必获取任何具有对给定记录的父引用的记录。首先,你会在哪里搜索? CKShare 根记录的子记录不会出现在您的共享数据库中,您无权访问其他用户的私有区域。幸运的是,CloudKit 会将 CKShare 的根记录引用的所有子记录推送给您。以下方法也将解决第二个问题,您将自动收到任何和所有未来更改的通知!

关键是简单的在CloudKit容器中添加一个CKDatabaseSubscription到共享数据库。假设您是客户。每当另一个用户与您共享记录时,共享引用的 CKShare 记录和基础根记录都位于该用户私有数据库的自定义区域中。当您接受共享(触发应用程序委托方法 userDidAcceptCloudKitShareWith)时,same CKShare 和基础记录现在对您可见,除了它们都在您的 共享 数据库。如果您订阅了共享数据库,订阅将在您接受共享后立即启动并通知您。现在您可以使用 CKFetchDatabaseChangesOperation 获取共享数据库中的所有更改。在recordZoneWithIDChangedBlock中,会给出分享用户自定义区域的CKRecordZoneID。您使用它来触发一个 CKFetchRecordZoneChangesOperation(一定要在共享数据库中执行此操作!),其中 returns CKShare、底层根记录和 所有具有对基础引用记录的父引用

因此,通过简单的数据库订阅,您可以自动触发并下载所有共享、根记录和子项!