Запустите CKQueryOperation с результатами предыдущего CKQueryOperation - PullRequest
0 голосов
/ 04 августа 2020

У меня есть приложение, которое представляет собой список покупок. Я могу хранить цены на продукт и поставщика в своем приложении, модель:

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 (Vendor.name).

Я попытался l oop через 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 (), но я не могу понять, как это должно выглядеть в конце.

1 Ответ

0 голосов
/ 14 августа 2020

Допустим, вы используете операцию для получения цен, как указано выше.

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