【问题标题】:CloudKit - How to share multiple records and retrieve shared records?CloudKit - 如何共享多条记录并检索共享记录?
【发布时间】:2018-05-27 03:52:53
【问题描述】:

我上次观看了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

共享多条记录时,我遇到了这个问题

到目前为止我所做的尝试:

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

注1

Note2(将父级设为 Note1)

Note3(将父级设为 Note1)

我用下面的代码分享了 Note1(父记录):

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)

并使用以下代码检索共享笔记:

CODE - 从共享笔记中读取数据

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)
}

上述方法仅给出父注释数据(仅根/父)

查询:

1) 如何获取其他孩子的笔记记录? (我用儿童这个词来理解)

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

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

提前谢谢..!

【问题讨论】:

    标签: ios swift icloud cloudkit


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢您的回答,我会尝试您的方法并让您知道
    • @r-carney 这个描述很有帮助,虽然我还是有点困惑。 CKFetchRecordZonesOperation 中的哪个方法返回实际更改的记录?你碰巧在某个地方有这样的例子吗?谢谢!
    • @Clifton Labrum 我在制作演示应用程序时没有找到太多帮助我现在没有示例代码..通过苹果的文档会有所帮助
    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答。我可以将 CKReference 设置为子记录,但我仍然很困惑如何获取这些记录(当我共享记录的用户点击共享链接时)
    • 因为 AppDelegate 中只有 1 个方法从元数据接收父记录
    • 我可能需要几天时间才能发布示例,但我将尝试在此处描述该方法:订阅将触发通知。您从通知中获取父记录的记录 ID。然后查询引用字段等于该记录 ID 的所有其他记录。
    • 谢谢...我能够从区域中获取所有共享记录...为什么我不能删除父记录,因为它给了我错误“引用违规”...任何想法?跨度>
    • 这很有趣,我从未见过这个错误,但你是最近在 SO 上提到它的第二个人。我还没有迁移到 IOS 11,现在我害怕 Apple 破坏了某些东西。使用仪表板中的相关代码和架构屏幕截图可能值得自己提出问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    相关资源
    最近更新 更多