我正在编写一个带有groupchatID(String)的函数,并返回该组聊天的收件人列表([String])。然而,我正在努力与函数的异步部分。当我运行该函数时,它正确地向控制台打印我正在寻找的用户名数组。虽然,当我调用函数并尝试打印返回的值时,它总是一个空数组,因为该函数在firebase调用完成之前返回数组。我试图使用回调,但我不太明白它的语法。请看一下,让我知道需要改变什么。
功能:
func GetRecipientsFor(GroupChatID :String , completion: @escaping ([String]) -> ()) {
var returnArray: [String] = [""]
rootRef.child("chatMembers").child(GroupChatID).observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children.allObjects {
var append = child as! FIRDataSnapshot
returnArray.append((append.key as String))
print("Return Array Currently Contains: \(returnArray)")
//The above printout works properly and when the for loop finishes, the array is exactly as I want it
}
completion(returnArray)
//BUT, this portion returns an empty array
})
}
我如何调用该函数:
GetRecipientsFor(GroupChatID: gchatID) { (result) -> () in
print(result)
}
新功能调用
var recipients : [String] = [""]
DispatchQueue.main.async {
GetRecipientsFor(GroupChatID: gchatID) { result in
print(result) //PRINTS CORRECTLY!!!
recipients = result
}
}
print(recipients) //PRINTS A BLANK ARRAY
答案 0 :(得分:2)
的问题
var recipients : [String] = [""]
DispatchQueue.main.async {
GetRecipientsFor(GroupChatID: gchatID) { result in
print(result)
recipients = result
}
}
print(recipients) // Completes before recipients = result
是在异步调用之前发生的最后一行。
在print(recipients)
之前解释更进一步的recipients = result
。使用收件人的所有逻辑都需要在该完成块内发生。您需要做的就是
func getRecipients(completion: @escaping ([String]) -> ()) {
var recipients : [String] = [""]
DispatchQueue.main.async {
GetRecipientsFor(GroupChatID: gchatID) { result in
print(result)
completion(result)
}
}
}
如果您想要包含更多逻辑,则可以在完成内调用函数,即handleResults(result)
。我认为阅读更多关于closures/completion blocks/and async calls的信息非常有益。
答案 1 :(得分:0)
你也可以简化它并使用firebase观察者异步任务为你的函数添加其他参数,如下所示:
//控制器是获取结果所需的位置
func GetRecipientsFor(GroupChatID :String , controller: UIViewController){
rootRef.observeSingleEvent(of: .value) { (snapshot) in
//here you haver your snapshot. do the stuff and
controller.setDataForRecipe(dataFromYourSnapshot)
}
}
在你的控制器中:
public func setDataForRecipe (arrayIngredients: [String]){
//whatever you want. example:
self.data = arrayIngredients
self.tableView.reloadData()
}