首页 > 解决方案 > 使用先前 CKQueryOperation 的结果运行 CKQueryOperation

问题描述

我有一个应用程序是一个购物清单。我可以在我的应用程序中存储每个产品和供应商的价格,模型是

Product
Vendor
Price

一种产品可以有来自不同供应商的多种价格。

我将价格信息与产品和供应商的引用一起存储(CKRecord.Reference)。

现在我正在使用以下内容来获取与产品相关的所有价格:

public func fetchDataByProduct(product: Product, completionHandler: @escaping (Bool) -> Void){
        self.pricesBuffer = []

        let cloudContainer = CKContainer.init(identifier: "iCloud.XYZ")

        let publicDatabase = cloudContainer.publicCloudDatabase
        let reference = CKRecord.Reference(recordID: product.recordID, action: .deleteSelf)

        let predicate = NSPredicate(format: "priceToProduct == %@", reference)

        let query = CKQuery(recordType: "Price", predicate: predicate)

        let operation = CKQueryOperation(query: query)
        operation.recordFetchedBlock = { record in

            let price = Price()
            price.recordID = record.recordID

            price.grossPrice = record.object(forKey: "grossPrice") as? Double

            let dummy = record.object(forKey: "priceToVendor") as! CKRecord.Reference

            price.vendorRecordID = dummy.recordID
            self.pricesBuffer.append(price)
        }

        operation.queryCompletionBlock = { [unowned self] (cursor, error) in
            self.pricesBuffer.forEach({price in
                price.retrieveVendor()
            })

            DispatchQueue.main.async {
                if error == nil {
                    self.prices = self.pricesBuffer
                    completionHandler(true)
                } else {
                }
            }
        }
        publicDatabase.add(operation)
    }

我现在的问题是我无法检索作为供应商对象 (Vendor.name) 一部分的供应商名称。

我试图遍历 priceBuffer 并按价格运行这个,但问题似乎是 CloudKit 首先完成对 fetchDataByProduct() 的初始请求,然后获取供应商数据但为时已晚,因为更新的数据没有得到推送到我的视图(SwiftUI)。

publicDatabase.fetch(withRecordID: self.vendorRecordID, completionHandler:  {[unowned self] record, error in
            if let record = record {
                print(record)
                self.vendor.recordID = record.recordID
                self.vendor.name = record["name"] as! String
                print(self.vendor.name)
            }
        })

任何想法如何解决这个问题?我相信我必须在混合中添加第二个 CKQueryOperation 并使用 .addDependency() 但我无法理解它最终应该是什么样子。

标签: swiftuicloudkitckqueryoperation

解决方案


假设您使用该操作来获取上述价格。

let predicate = NSPredicate(format: "priceToProduct == %@", reference)

let query = CKQuery(recordType: "Price", predicate: predicate)

let pricesOperation = CKQueryOperation(query: query)
pricesOperation.database = publicDatabase // not required if you don't use OperationQueue

然后你可以构造操作来获取供应商,我将创建简单的操作用于演示目的。

let vendorQuery = CKQuery(recordType: "Vendor", predicate: predicate)
    
let vendorsOperation = CKQueryOperation(query: vendorQuery)
vendorsOperation.database = publicDatabase // not required if you don't use OperationQueue

然后您可以设置依赖关系,首先获取价格而不是供应商。

vendorsOperation.addDependency(pricesOperation)

最后将这些操作提交给OperationQueue

let operationQueue = OperationQueue()
        
operationQueue.addOperations([pricesOperation, vendorsOperation], waitUntilFinished: false)

编辑:如果您不想使用OperationQueue,只需将这些操作提交到数据库,但在提交要执行的操作之前先设置依赖关系。

vendorsOperation.addDependency(pricesOperation)
publicDatabase.add(pricesOperation)
publicDatabase.add(vendorsOperation)

推荐阅读