Swift函数从异步firebase调用返回一个值

时间:2017-05-18 14:32:09

标签: ios swift asynchronous firebase firebase-realtime-database

我正在编写一个带有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

2 个答案:

答案 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()
}