如何在Swift中使用异步Firebase方法实例化类? [英] How to instantiate a class with asynchronous Firebase methods in Swift?
问题描述
我正在通过Firebase DataSnapshot实例化User
类.调用初始化程序init(snapshot: DataSnapshot)
时,它应该通过getFirebasePictureURL
和getFirebaseNameString
方法的@转义完成处理程序(使用Firebase的observeSingleEvent
方法)从两个不同的数据库引用(即pictureRef
和nameRef
)异步检索值. ).为了避免在初始化所有成员之前由闭包捕获'self'错误,我不得不使用临时值""
和URL(string: "initial")
初始化fullName
和pictureURL
.但是,当通过User(snapshot: DataSnapshot)
实例化类时,这些值实际上不会使用检索到的Firebase值进行实际更新.
I am instantiating a User
class via a Firebase DataSnapshot. Upon calling the initializer init(snapshot: DataSnapshot)
, it should asynchronously retrieve values from two distinct database references, namely pictureRef
and nameRef
, via the getFirebasePictureURL
and getFirebaseNameString
methods' @escaping completion handlers (using Firebase's observeSingleEvent
method). To avoid the 'self' captured by a closure before all members were initialized error, I had to initialize fullName
and pictureURL
with temporary values of ""
and URL(string: "initial")
. However, when instantiating the class via User(snapshot: DataSnapshot)
, these values are never actually updated with the retrieved Firebase values.
import Firebase
class User {
var uid: String
var fullName: String? = ""
var pictureURL: URL? = URL(string: "initial")
//DataSnapshot Initializer
init(snapshot: DataSnapshot) {
self.uid = snapshot.key
getFirebasePictureURL(userId: uid) { (url) in
self.getFirebaseNameString(userId: self.uid) { (fullName) in
self.fullName = fullName
self.profilePictureURL = url
}
}
func getFirebasePictureURL(userId: String, completion: @escaping (_ url: URL) -> Void) {
let currentUserId = userId
//Firebase database picture reference
let pictureRef = Database.database().reference(withPath: "pictureChildPath")
pictureRef.observeSingleEvent(of: .value, with: { snapshot in
//Picture url string
let pictureString = snapshot.value as! String
//Completion handler (escaping)
completion(URL(string: pictureString)!)
})
}
func getFirebaseNameString(userId: String, completion: @escaping (_ fullName: String) -> Void) {
let currentUserId = userId
//Firebase database name reference
let nameRef = Database.database().reference(withPath: "nameChildPath")
nameRef.observeSingleEvent(of: .value, with: { snapshot in
let fullName = snapshot.value as? String
//Completion handler (escaping)
completion(fullName!)
})
}
}
是否有发生这种情况的原因,我将如何解决此问题,使其确实初始化为检索到的值,而不是仅保留临时值?是因为
init
不是异步的吗?
我正在从Firebase数据库的一个节点读取数据,并使用该数据创建一个新的节点子节点.初始化User类的方法将在数据库中创建此新节点,如下所示:
I am reading data from one node of the Firebase database and, using that data, creating a new node child. The method that initializes the User class will create this new node in the database as:
如您所见,子代会使用临时值进行更新,因此似乎程序执行不会等待回调.
As you can see, the children are updated with the temporary values so it seems the program execution does not wait for the callback.
任何帮助将不胜感激!
推荐答案
这很hacky.
您应该在init
方法中添加completionHandler
.因此,当您的异步调用完成时,您将获得对象的实际值.
You should add completionHandler
in init
method. So, when your asynchronous call completed you will get actual value of object.
init(snapshot: DataSnapshot, completionHandler: @escaping (User) -> Void) {
self.uid = snapshot.key
getFirebasePictureURL(userId: uid) { (url) in
self.getFirebaseNameString(userId: self.uid) { (fullName) in
self.fullName = fullName
self.profilePictureURL = url
completionHandler(self)
}
}
}
我希望这会对您有所帮助.
I hope this will help you.
这篇关于如何在Swift中使用异步Firebase方法实例化类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!