我想从queryCompletionBlock检索值并将其发送到另一个viewController

这是我的代码:

func KcalCloudKitData() {
    publicDatabase = container.publicCloudDatabase
    allRecords = []
    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: "Kcal", predicate: predicate)
    query.sortDescriptors = [NSSortDescriptor(key: "KcalCoef", ascending: true)]
    let queryOperation = CKQueryOperation(query: query)

    queryOperation.recordFetchedBlock = {(record: CKRecord) in
        self.allRecords.append(record)
    }

    queryOperation.queryCompletionBlock = {cursor, error in
        if error != nil {
            print("Failed loading data from iCloud")
            //print(error?.localizedFailureReason)
        } else {

            for value in self.allRecords {
                self.kcalUnitValid.append(value.object(forKey: "KcalValidUnit") as! [String])
            }
        //self.performSegue(withIdentifier: "AppLoaded", sender: nil)
        }
    }
    print(self.kcalUnitValid)
    publicDatabase?.add(queryOperation)
}


当我在完成块之外使用代码print(self.kcalUnitValid)打印时,这将获得一个空表。有什么办法吗?

提前致谢。

最佳答案

queryCompletionBlock是异步执行的,因此到print(self.kcalUnitValid)被调用时,queryCompletionBlock尚未完成执行,换句话说,执行发生的顺序如下:


1.- queryOperation.queryCompletionBlock(..)被称为
2.- print(self.kcalUnitValid)称为// prints empty
3.-几秒钟后,返回queryOperation.queryCompletionBlock(..)的结果






您可能会执行以下操作:

func KcalCloudKitData() {
  // .. code omitted
  queryOperation.queryCompletionBlock = {cursor, error in
    if error != nil {
      // .. code omitted
    } else {
      for value in self.allRecords {
        self.kcalUnitValid.append(value.object(forKey: "KcalValidUnit") as! [String])
      }

      // Segue to another ViewController
      // And also sending kcalUnitValid
      self.performSegue(withIdentifier: "AppLoaded", sender: self.kcalUnitValid)
    }
  }
  // .. code omitted
}

// Actually in this method is when you decide
// what data you are going to send to the AnotherViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if segue.identifier == "AppLoaded" {
    let anotherViewController = segue.destination as! AnotherViewController
    anotherViewController.kcalUnitValid = sender as! Array<[String]>
  }
}


资源:

Watch this video explaning async programming in Swift

关于ios - 如何从完成块返回值以在其他viewController中使用它?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39806800/

10-11 19:55