我需要从 Firebase 读取一个值,然后在总共两个对象的事务中将其与多个其他值一起写入 Firebase。
我正在创建一个聊天室,因此当发送消息时,我正在为两个联系人创建一个聊天室,每个人都有自己的聊天室。我的代码:
private func CreateChatRoom(creatorID: String, creatorName: String ,contactID: String, contactName: String)
{
var creatorImageString: String = ""
var contactImageString: String = ""
ReadContactImage(contactID: contactID)
{
success in
if success
{
contactImageString = self.tempContactImg
}
}
ReadContactImage(contactID: creatorID)
{
success in
if success
{
creatorImageString = self.tempContactImg
}
}
let infoForCreator = [Constants.Chat.ChatRoomsLite.CONTACT_NAME: contactName,
Constants.Chat.ChatRoomsLite.CONTACT_ID: contactID,
Constants.Chat.ChatRoomsLite.NUM_OF_UNREAD_MSGS : 0,
Constants.Chat.ChatRoomsLite.CONTACT_IMG_URL: contactImageString] as [String : Any]
let infoForContact = [Constants.Chat.ChatRoomsLite.CONTACT_NAME: creatorName,
Constants.Chat.ChatRoomsLite.CONTACT_ID: creatorID,
Constants.Chat.ChatRoomsLite.NUM_OF_UNREAD_MSGS : 0,
Constants.Chat.ChatRoomsLite.CONTACT_IMG_URL: creatorImageString] as [String : Any]
let childUpdates = ["\(creatorID)/\(contactID)/": infoForCreator,
"\(contactID)/\(creatorID)/": infoForContact
]
Constants.refs.databaseChatsLite.updateChildValues(childUpdates)
}
private func ReadContactImage(contactID: String, completion: @escaping (Bool) -> ())
{
Constants.refs.databaseUsers.child(contactID).child(Constants.Account.AccountFields.USER_IMAGE_STR).observeSingleEvent(of: .value, with: {(snapshot) in
self.tempContactImg = (snapshot.value as? String)!
completion(true)
})
}
var tempContactImg : String = "";
我在这里读到函数“ReadContactImage”应该同步运行,但事实并非如此。所以我留下了空的联系人图像。
我想过在同一个函数中读取两个图像,但是 CreateChatRoom
也需要同步,所以基本上我遇到了同样的问题。
有谁知道如何正确处理这个问题吗?
是否有更简单的方法可以做到这一点?
编辑:
如果写入数据库是异步的,我会在这里得到一个异常:
func AddChatToCollections(chatAsDictionary: NSDictionary!)
{
if chatAsDictionary == nil
{
return
}
let contactName = chatAsDictionary[Constants.Chat.ChatRoomsLite.CONTACT_NAME] as! String
let contactImg = chatAsDictionary[Constants.Chat.ChatRoomsLite.CONTACT_IMG_URL] as! String
//let lastMsg = chatAsDictionary["lastMessage"] as! String
let newMsgs = chatAsDictionary[Constants.Chat.ChatRoomsLite.NUM_OF_UNREAD_MSGS] as! Int
let contactID = chatAsDictionary[Constants.Chat.ChatRoomsLite.CONTACT_ID] as! String
let chatToAdd = PrivateChatLiteObject(chattingWith: contactName, ContactID: contactID, unreadMessages: newMsgs, LastMSG: "", ContactImageStr: contactImg)
chatsDictionary[contactID] = chatToAdd
chatsIndex.append(contactID)
}
当尝试使用字典中的信息时,该信息取自 Firebase。 该函数从这里调用:
private func populateActiveChats()
{
let loggedOnUserID = Auth.auth().currentUser?.uid
let ref = Constants.refs.databaseChatsLite.child(loggedOnUserID!)
// Retrieve the products and listen for changes
ref.observe(.value, with:
{ (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot]
{
if (self.chatsDictionary.keys.contains(child.key) == false)
{
let chatValueDictionary = child.value as? NSDictionary
self.AddChatToCollections(chatAsDictionary: chatValueDictionary)
self.DispatchQueueFunc()
}
}
})
}
当我打开聊天页面时,从 viewDidLoad()
调用它。
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
因为 chatAsDictionary[CONTACT_NAME] 不存在,因为当 chatAsDictionary 从 Firebase 获取数据时,它还没有从异步函数写入那里
最佳答案
您调用的这两种方法都会从 Firebase 异步加载数据。在对 ReadContactImage
的两次调用完成之前,您无法构造 infoForCreator
(等)。
一个简单的方法是嵌套调用:
var creatorImageString: String = ""
var contactImageString: String = ""
ReadContactImage(contactID: contactID)
{
success in
if success
{
contactImageString = self.tempContactImg
ReadContactImage(contactID: creatorID)
{
success in
if success
{
creatorImageString = self.tempContactImg
let infoForCreator = [Constants.Chat.ChatRoomsLite.CONTACT_NAME: contactName,
Constants.Chat.ChatRoomsLite.CONTACT_ID: contactID,
Constants.Chat.ChatRoomsLite.NUM_OF_UNREAD_MSGS : 0,
Constants.Chat.ChatRoomsLite.CONTACT_IMG_URL: contactImageString] as [String : Any]
let infoForContact = [Constants.Chat.ChatRoomsLite.CONTACT_NAME: creatorName,
Constants.Chat.ChatRoomsLite.CONTACT_ID: creatorID,
Constants.Chat.ChatRoomsLite.NUM_OF_UNREAD_MSGS : 0,
Constants.Chat.ChatRoomsLite.CONTACT_IMG_URL: creatorImageString] as [String : Any]
let childUpdates = ["\(creatorID)/\(contactID)/": infoForCreator,
"\(contactID)/\(creatorID)/": infoForContact
]
Constants.refs.databaseChatsLite.updateChildValues(childUpdates)
}
}
}
}
或者,您可以保留一个计数器:
var creatorImageString: String = ""
var contactImageString: String = ""
var completedCount = 0;
ReadContactImage(contactID: contactID)
{
success in
if success
{
contactImageString = self.tempContactImg
completedCount++
if completedCount == 2
{
createDatabaseNode(contactImageString, creatorImageString)
}
}
}
ReadContactImage(contactID: creatorID)
{
success in
if success
{
creatorImageString = self.tempContactImg
completedCount++
if completedCount == 2
{
createDatabaseNode(contactImageString, creatorImageString)
}
}
}
然后 createDatabaseNode
是一个函数,其中包含用于填充数据结构并调用 updateChildValues
的代码。
关于swift - 从 Firebase 同步读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53103305/