我正在尝试创建一个带有FIRUser和FIRDatabaseReference的失败初始化程序的类。它从Firebase数据库下载数据,并根据返回的内容设置自己的变量。否则,初始化程序应该失败。
发生的情况是,数据是在闭包中下载的,但是随后一切都恢复为默认值,好像从未发生过下载一样!
我真的很想在类初始化程序中包含此服务器聊天逻辑。有什么办法可以我安全地做到这一点吗?到目前为止,我已经尝试了很多方法,但仍无法解决。
init?(from user: FIRUser, withUserReference ref: FIRDatabaseReference){
let userID = user.uid
var init_succeeded = false
//These values don't matter. If the init fails
//It'll return an empty class.
//Yes this is a hack lol
self.incognito = false
self.email = "NO"
self.username = "NOPE"
self.ref = ref
self.fir_user = user
self.mute_all = false
//Getting the information from the database
ref.child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
//Unpacking user preferences
self.incognito = (value?["incognito"] as? Bool)!
self.mute_all = (value?["mute_all"] as? Bool)!
self.email = (value?["email"] as? String)!
self.username = (value?["username"] as? String)!
init_succeeded = true
}) { (error) in
print("ERROR : \(error.localizedDescription)")
}
if !init_succeeded { return nil }
}
谢谢! -基南
最佳答案
简单答案:否
当函数依赖异步语句时,您根本不应该在函数中使用return
值。
此方法将始终返回nil,因为在该方法返回后,很可能将init_succeeded
设置为true
。请记住,Firebase查询是异步的,因此一旦您调用observeSingleEvent
,该函数就不会等待该语句完成执行,它只是异步运行它,并继续处理其余代码(在代码中为return
这个案例)。
完成闭包是您可以获得的最接近的闭包(但是您的代码将不会完全包含在初始化器中):
init(from user: FIRUser, withUserReference ref: FIRDatabaseReference, completion: @escaping (Bool) -> Void){
let userID = user.uid
// default values
self.incognito = false
self.email = "NO"
self.username = "NOPE"
self.ref = ref
self.fir_user = user
self.mute_all = false
//Getting the information from the database
ref.child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
//Unpacking user preferences
self.incognito = (value?["incognito"] as? Bool)!
self.mute_all = (value?["mute_all"] as? Bool)!
self.email = (value?["email"] as? String)!
self.username = (value?["username"] as? String)!
completion(true) // true = success
}) { (error) in
completion(false) // false = failed
print("ERROR : \(error.localizedDescription)")
}
}
现在基本上像这样使用它
let myObject = myClass(from: someUser, withUserReference: someRef, completion: { success in
if success {
// initialization succeeded
}
else {
// initialization failed
}
})
我建议尽管一般不要在初始化器中检索数据。也许编写另一个专门用于检索数据的函数,并且仅在
init()
中设置默认值关于ios - 从Firebase数据提取初始化类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41584486/