我想从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)
打印时,这将获得一个空表。任何解决方案?
提前致谢。
答案 0 :(得分:0)
这是因为在任务完成后调用完成闭包(块是Objective-C的术语):例如你的
self.kcalUnitValid.append(...)
任务比行
晚完成print(self.kcalUnitValid)
无论它位于控制器中的打印代码之前。
当queryOperation准备好时,将触发完成处理程序。这应该发生在你的印刷品之后。
所以你应该例如在封闭内打印该值。
queryOperation.queryCompletionBlock = {cursor, error in
...
self.kcalUnitValid.append(value.object(forKey: "KcalValidUnit") as! [String])
print(self.kcalUnitValid)
...
}
答案 1 :(得分:0)
您无法从完成块返回值,因此请使用另一个完成块(作为方法的参数),并在完成任务时调用它,例如,
func hardProcessingWithString(input: String, completion: (result: String) -> Void) {
...
completion("we finished!")
}
你可以像使用
一样使用它hardProcessingWithString("commands") {
(result: String) in
print("got back: \(result)")
}
所以编写一个函数,可以在完成你想要执行的任务时调用它自己的完成处理程序。
参考:
答案 2 :(得分:0)
queryCompletionBlock
是异步执行的,所以当调用print(self.kcalUnitValid)
时queryCompletionBlock
还没有完成执行,换句话说,是如何执行如下:
queryOperation.queryCompletionBlock(..)
被称为 print(self.kcalUnitValid)
被称为 // prints empty
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]>
}
}