У меня есть значение, которое мне нужно прочитать из 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 = "";
Я прочитал здесь на SO, что функция "ReadContactImage" должна работать синхронно, но это не так. Так что я остался с пустыми изображениями контактов.
Я думал о том, чтобы просто прочитать оба изображения в одной и той же функции, но CreateChatRoom
также должен быть синхронным, поэтому в принципе у меня осталась одна и та же проблема.
Кто-нибудь знает, как правильно с этим справиться?
Может быть, есть более простой способ сделать это?
Edit:
Если запись в базу данных асинхронна, я получаю исключение:
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, они еще не записываются туда из асинхронной функции