【发布时间】:2019-09-13 07:55:02
【问题描述】:
我正在通过 Firebase DataSnapshot 实例化 User 类。在调用初始化程序init(snapshot: DataSnapshot) 时,它应该通过getFirebasePictureURL 和getFirebaseNameString 方法的@escaping 完成处理程序(使用Firebase 的observeSingleEvent 方法)从两个不同的数据库引用中异步检索值,即pictureRef 和nameRef )。为了避免在所有成员初始化之前被闭包捕获的'self'错误,我不得不使用"" 和URL(string: "initial") 的临时值初始化fullName 和pictureURL。但是,当通过User(snapshot: DataSnapshot) 实例化类时,这些值实际上从未使用检索到的 Firebase 值进行更新。
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 类的方法会在数据库中创建这个新节点为:
如您所见,子项使用临时值更新,因此程序执行似乎不等待回调。
任何帮助将不胜感激!
【问题讨论】:
-
有一个答案可能会有所帮助,但这里似乎有很多不必要的代码。也许需要它,但您是否有一个用户 uid、用户名和个人资料图片 url 存储在三个单独的 firebase 节点中的情况?此外,您有一个类 var self.uid,这很好,一个类 var,不需要将它传递给任何函数,因为它对整个类都可用,而且它是第一件事.你是在课外调用你的函数吗?
-
@Jay 谢谢!我意识到我没有必要使用
uid作为论据。这三个数据点都是单个节点的子节点,因此很多代码可能是多余的。不会从类外部调用 get 方法——仅在类实例化时调用。 -
如果所有数据点都包含在一个节点中,那么大部分代码都是不必要的。让我尝试一个答案,看看这是否让代码更易于管理。
-
更新了我的答案,但问题中有一些未知数;为什么 -Lomc6GG..." 有 *author 的子节点?父节点是什么?您正在使用回调,但可能不需要,特别是如果您的代码正在观察包含作者数据,因为如果添加了新作者,它将通过事件传递到您的应用程序。关于发布的另一件事:我们经常需要在答案中使用结构,因此它们应该作为文本包含,这样我们就不必重新键入它们。要获取您的 Firebase 结构,请使用 Firebase 控制台->导出 JSON 并复制并粘贴您的结构的 sn-p。
标签: swift firebase firebase-realtime-database