我正在尝试从Firebase加载用户名,而该用户名应该在Object中设置。但是,在已经设置名称后,将调用Firebase Observe Command。有什么问题,我该如何解决?
let ref = Database.database().reference().child("Users").child(currentMessage.senderId).child("name")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
// This is supposed to be called first
self.username = snapshot.value as! String
print(self.username)
})
// This somehow gets called first
let nameModel = NameModel(name: self.username, uid: *some UID*)
decoratedItems.append(DecoratedChatItem(chatItem: nameModel, decorationAttributes: nil))
答案 0 :(得分:1)
Firebase异步加载其数据库中的数据。这意味着代码的执行顺序与您期望的顺序不同。最简单的方法是使用一些日志语句:
let ref = Database.database().reference().child("Users").child(currentMessage.senderId).child("name")
print("Before attaching observer")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
print("In completion handler")
})
print("After attaching observer")
与您的预期不同,此代码打印:
在加入观察者之前
附上观察员后
在完成处理程序
中
这是因为从Firebase(或任何其他Web服务)加载数据可能需要一些时间。如果代码等待,则会阻止用户与您的应用程序进行交互。因此,Firebase会在后台加载数据,并让您的代码继续运行。然后,当数据可用时,它会调用您的完成处理程序。
习惯这种模式的最简单方法是重新构建您的问题。而不是说“首先加载数据,然后将其添加到列表中”,将问题框架为“开始加载数据。加载数据时,将其添加到列表中”。
在代码中,这意味着您将需要数据的任何代码移动到完成处理程序中:
let ref = Database.database().reference().child("Users").child(currentMessage.senderId).child("name")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
self.username = snapshot.value as! String
let nameModel = NameModel(name: self.username, uid: *some UID*)
decoratedItems.append(DecoratedChatItem(chatItem: nameModel, decorationAttributes: nil))
})
有关此主题的更多问题,请参阅: