简体   繁体   English

使用先前 CKQueryOperation 的结果运行 CKQueryOperation

[英]Run CKQueryOperation with results from previous CKQueryOperation

I have an app that is a shopping list.我有一个购物清单应用程序。 I can store prices per product and vendor in my app, the model is我可以在我的应用程序中存储每个产品和供应商的价格,model 是

Product
Vendor
Price

One product can have multiple prices from different vendors.一种产品可以有来自不同供应商的多种价格。

I store the price information with references to the product and vendor (CKRecord.Reference).我存储价格信息以及对产品和供应商的引用 (CKRecord.Reference)。

Now I am using the below to fetch all the prices related to a product:现在我使用下面的方法获取与产品相关的所有价格:

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

My problem is now that I cannot retrieve the vendor name which is part of the Vendor object (Vendor.name).我现在的问题是我无法检索作为供应商 object (Vendor.name) 一部分的供应商名称。

I have tried to loop over the pricesBuffer and run this one per price but the problem seems to be that CloudKit first completes the initial request to fetchDataByProduct() and then afterwards fetches the vendor data but then its too late because that updated data does not get pushed to my View (SwiftUI).我试图遍历 pricesBuffer 并按价格运行这个,但问题似乎是 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)
            }
        })

Any ideas how to solve this?任何想法如何解决这个问题? I believe I have to add a second CKQueryOperation to the mix and use the.addDependency() but I cannot wrap my head around how that should look like in the end.我相信我必须将第二个 CKQueryOperation 添加到组合中并使用 .addDependency() 但我无法理解它最终应该是什么样子。

Let's say you use the operation to fetch prices like above.假设您使用该操作来获取上述价格。

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

Then you can construct operation to fetch vendors, I will create simple operation for demo purposes.然后你可以构造操作来获取供应商,我将创建简单的操作用于演示目的。

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

Then you can set dependency, first fetch prices than vendors.然后可以设置依赖关系,先取比厂商的价格。

vendorsOperation.addDependency(pricesOperation)

And lastly submit those operations to OperationQueue最后将这些操作提交给OperationQueue

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

Edit: If you don't want to use OperationQueue , simply submit those operations to database, but first set dependency before submitting the operations to be executed.编辑:如果您不想使用OperationQueue ,只需将这些操作提交给数据库,但在提交要执行的操作之前首先设置依赖关系。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM