ios - 从 Firebase 数据拉取初始化类

标签 ios swift firebase firebase-realtime-database

我正在尝试创建一个带有可失败初始化程序的类,该初始化程序采用 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 }
}

谢谢! - 基南

最佳答案

简单回答:

当函数依赖于异步语句时,您不应该返回函数的值。 此方法将始终返回 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/

相关文章:

firebase - 无法在 Firebase Cloud Messaging Console 中上传 APN

ios - 核心数据 TableView Controller 的重复条目以及如何使用 NSFetchedResultsController 处理此问题

ios - 如何检测 UITextView 中的图像删除

ios - 使用自定义注释移动动画 IOS Swift Like Ola Uber App MapKit

android - Xamarin,火力地堡 : "Default FirebaseApp is not initialized in this process" - though initializeApp() is called?

ios - 无法将 firebase 数据库下载到我的应用程序

iphone - 智能 CVS 和核心数据

ios - swift 3 : Create UIImage from UIBezierPath

ios - 使用 Alamofire 和 Swift 3 反序列化复杂的 JSON

swift - 从 UICollectionView 打印图像名称到控制台