如何在Swift中使用异步Firebase方法实例化类? [英] How to instantiate a class with asynchronous Firebase methods in Swift?

查看:61
本文介绍了如何在Swift中使用异步Firebase方法实例化类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过Firebase DataSnapshot实例化User类.调用初始化程序init(snapshot: DataSnapshot)时,它应该通过getFirebasePictureURLgetFirebaseNameString方法的@转义完成处理程序(使用Firebase的observeSingleEvent方法)从两个不同的数据库引用(即pictureRefnameRef)异步检索值. ).为了避免在初始化所有成员之前由闭包捕获'self'错误,我不得不使用临时值""URL(string: "initial")初始化fullNamepictureURL.但是,当通过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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆