CloudKit 分享

Posted

技术标签:

【中文标题】CloudKit 分享【英文标题】:CloudKit Sharing 【发布时间】:2016-11-15 06:45:40 【问题描述】:

我无法理解一些 CloudKit 共享概念,而且 WWDC 2016“CloudKit 的新功能”视频似乎没有解释允许用户共享和访问共享记录所需的所有内容。

我已成功创建了一个应用程序,允许用户在其私人数据库中创建和编辑记录。 我还能够创建共享记录并使用提供的共享 UIController 共享它。这可以被参与者用户成功接收和接受,但我不知道如何查询和显示这个共享记录。

应用程序在用户私有数据库中创建一个“MainZone”,然后在这个“MainZone”中创建一个 CKRecord。然后我创建并保存一个 CKShare 记录并使用它来显示 UICloudSharingController。

如何查询 sharedDatabase 以访问此记录?我尝试使用与 privateDatabase 中相同的查询,但出现以下错误:

"ShareDB can't be used to access local zone"

编辑

我发现了问题 - 我需要处理 AppDelegate 中接受的记录。现在它们出现在 CloudKit 仪表板中,但我仍然无法查询它们。看来我可能需要获取 sharedDatabase“MainZone”才能查询它们。

【问题讨论】:

【参考方案1】:

老兄,我明白了:首先,您需要获取该共享记录的 CKRecordZone。您可以通过以下方式做到这一点:

let sharedData = CKContainer.default().sharedCloudDatabase
    sharedData.fetchAllRecordZones  (recordZone, error) in
        if error != nil 
            print(error?.localizedDescription)
        
        if let recordZones = recordZone 
            // Here you'll have an array of CKRecordZone that is in your SharedDB!
        
    

现在,有了这个数组,你所要做的就是正常获取:

func showData(id: CKRecordZoneID) 

    ctUsers = [CKRecord]()

    let sharedData = CKContainer.default().sharedCloudDatabase
    let predicate = NSPredicate(format: "TRUEPREDICATE")
    let query = CKQuery(recordType: "Elder", predicate: predicate)

    sharedData.perform(query, inZoneWith: id)  results, error in
        if let error = error 
            DispatchQueue.main.async 
                print("Cloud Query Error - Fetch Establishments: \(error)")
            
            return
        
        if let users = results 
            print(results)
            self.ctUsers = users
            print("\nHow many shares in cloud: \(self.ctUsers.count)\n")
            if self.ctUsers.count != 0 
                // Here you'll your Shared CKRecords!
            
            else 
                print("No shares in SharedDB\n")
            
        
    

【讨论】:

我不推荐这种方法,如果有数百万用户共享内容会怎样?将有数百万个记录区,所以这个查询可能非常大。我认为正确的方法似乎是存储对与用户共享的内容的本地引用,并使用它们来查询更改。我认为这个想法也是尽量减少查询,而是注册更改然后处理更改 - 但是我担心在某些情况下可能会导致过多的推送流量。 嗯——实际上你可能是对的,因为用户只会看到与他们共享的记录中的区域!【参考方案2】:

我不太了解何时您想获得这些信息。我和你有同样的问题,但我只能通过单击 URL 来获取共享数据......为此,你需要两个函数。 AppDelegate 中的第一个:

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 viewController: ViewController = self.window?.rootViewController as! ViewController
            viewController.fetchShare(cloudKitShareMetadata)
        
    
    CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptSharesOperation)

ViewConroller 中,您拥有将获取此元数据的函数:

func fetchShare(_ metadata: CKShareMetadata) 
    let operation = CKFetchRecordsOperation(recordIDs: [metadata.rootRecordID])
    operation.perRecordCompletionBlock =  record, _, error in
        if error != nil 
            print(error?.localizedDescription)
        
        if record != nil 
            DispatchQueue.main.async() 
                self.currentRecord = record
                //now you have your Shared Record
            
        
    
    operation.fetchRecordsCompletionBlock =  _, error in
        if error != nil 
            print(error?.localizedDescription)
        
    
    CKContainer.default().sharedCloudDatabase.add(operation)

正如我之前所说,我现在尝试在不访问 URL 的情况下获取 ShareDB。一旦我接受了共享,我就不想依赖链接。希望对您有所帮助!

【讨论】:

谢谢,这是有道理的,但是我将如何从数据库中查询所有共享记录,或者应用程序是否希望保留这些共享记录的自己的副本(本地或私有数据库中)?我不想在本地存储数据我只想查询共享记录但似乎没有办法做到这一点,除非通过查询每个共享区域。 可悲的是,我和你在同一个地方,试图弄清楚这一点。共享内容不会保留在您的 privateDB 中,而是保留在 sharedDB 中。我试图做的是像普通的CKRecord一样查询,毕竟CKShare是对CKRecord的引用!但是,一旦我使用 ZoneID 执行查询,我就会收到相同的消息,即“ShareDB 不能用于访问本地区域” 我检查了记录 zoneID 并在 zoneID 中查询,效果很好。所以我保留私有数据库 zoneID 并与记录 zoneID 进行比较,如果它们不匹配,那么我知道它必须是 sharedDatabase 查询,然后查询中需要 zoneID。现在,我将在 privateDatabase 中存储所有 Shared zoneID 的副本,以便轻松了解要在 sharedDatabase 中查询哪些区域。 我明白了,出现“ShareDB can't be used to access local zone”的消息是因为我使用的是privateDB的ZoneID,而不是sharedDB!

以上是关于CloudKit 分享的主要内容,如果未能解决你的问题,请参考以下文章

CloudKit 设计建议

CloudKit - 通过 URL 在用户之间共享文件

如果所有者从 CloudKit 上的 CKShare 中删除我,如何通知我

为啥我不能从 Xcode 或 CloudKit Dashboard 查询 CloudKit?

CloudKit iOS 10 错误:帐户无权访问 CloudKit 帐户

CloudKit 批量获取?