Swift: Firebase Chat App Part 12 - Loading Conversations & Messages (Real-time) - Xcode 11 - 2020
/// Creates a new conversation with target user email and first message sent
func createNewConversation(with otherUserEmail: String, name: String, firstMessage: Message, completionHandler: @escaping ((Bool) -> Void)) {
guard
let currentEmail = UserDefaults.standard.value(forKey: "email") as? String,
let platformString = UserDefaults.standard.value(forKey: "platform") as? String,
let platform = Platform(rawValue: platformString) else {
completionHandler(false)
return
}
let safeEmail = DatabaseManager.safeEmail(emailAddress: currentEmail, platform: platform)
let ref = database.child("\(safeEmail)")
ref.observeSingleEvent(of: .value) { [weak self] snapshot in
guard let self = self else { return }
guard var userNode = snapshot.value as? [String : Any] else {
completionHandler(false)
print("User not found")
return
}
let messageDate = firstMessage.sentDate
let dateString = DateFormatter.dateFormatter.string(from: messageDate)
var message = ""
switch firstMessage.kind {
case .text(let messageText):
message = messageText
break
case .attributedText(_):
break
case .photo(_):
break
case .video(_):
break
case .location(_):
break
case .emoji(_):
break
case .audio(_):
break
case .contact(_):
break
case .linkPreview(_):
break
case .custom(_):
break
@unknown default:
break
}
let conversationID = "conversation_" + firstMessage.messageId
let newConversationData: [String:Any] = [
"id" : conversationID,
"name" : name,
"other_user_email" : otherUserEmail,
"latest_message" : [
"date" : dateString,
"message" : message,
"is_read" : false
]
]
let recipient_newConversationData: [String:Any] = [
"id" : conversationID,
"name" : "Self",
"other_user_email" : safeEmail,
"latest_message" : [
"date" : dateString,
"message" : message,
"is_read" : false
]
]
// Update recipient conversation entry
self.database.child("\(otherUserEmail)/conversations").observeSingleEvent(of: .value) { [weak self] snapshot in
guard let self = self else { return }
if var conversations = snapshot.value as? [[String:Any]] {
// append this conversation
conversations.append(recipient_newConversationData)
self.database.child("\(otherUserEmail)/conversations").setValue(conversations)
} else {
// create new conversation
self.database.child("\(otherUserEmail)/conversations").setValue([recipient_newConversationData])
}
}
// Update current user conversation entry
if var conversations = userNode["conversations"] as? [[String : Any]] {
// Conversation array exists for current user
// you should append
conversations.append(newConversationData)
userNode["conversations"] = conversations
} else {
// Conversation array does not exist
// Create it
userNode["conversations"] = [
newConversationData
]
}
ref.setValue(userNode) { [weak self] error, _ in
guard let self = self else { return }
guard error == nil else {
completionHandler(false)
return
}
self.finishCreatingConversation(name: name, conversationID: conversationID, firstMessage: firstMessage, completionHandler: completionHandler)
}
}
}
/// Gets all messages for a given conversation
func getAllMessagesForConversation(with id: String, completionHandler: @escaping ((Result<[Message], Error>) -> Void)) {
database.child("\(id)/messages").observe(.value) { snapshot in
guard let value = snapshot.value as? [[String:Any]] else {
completionHandler(.failure(DatabaseErrors.failedToFetch))
return
}
let messages: [Message] = value.compactMap { dictionary in
guard
let name = dictionary["name"] as? String,
let type = dictionary["type"] as? String,
let isRead = dictionary["is_read"] as? Bool,
let content = dictionary["content"] as? String,
let messageID = dictionary["id"] as? String,
let senderEmail = dictionary["sender_email"] as? String,
let dateString = dictionary["date"] as? String,
let date = DateFormatter.dateFormatter.date(from: dateString) else {
return nil
}
let sender = Sender(photoURLString: "", senderId: senderEmail, displayName: name)
return Message(sender: sender,
messageId: messageID,
sentDate: date,
kind: .text(content))
}
completionHandler(.success(messages))
}
}
id
를 통해 검색If you're building a real-time chat experience like in a Firebase chat app, having user identity verification can add a layer of trust and security. For developers targeting users in Qatar, integrating a check through the official https://visacheckqatar.com/ system could help validate user IDs before accessing sensitive messaging features. This ensures smoother onboarding and aligns with local digital ID standards.
Really helpful breakdown of how to structure Firebase queries with UIKit — especially the way you're handling conversation loading! If you're planning to scale this app or demo it through video content, it might also be useful to ensure your YouTube channel is eligible for monetization. You can use this free https://monetize-checker.com/ to quickly verify your channel’s monetization status. A good way to make sure you're not missing out on revenue as you share your builds.
Your UIKit Firebase Chat App looks promising! It's impressive to see the progress on loading conversations and messages. If you're curious about creating a full-fledged messaging app like WhatsApp, check out this insightful article for valuable insights: https://www.cleveroad.com/blog/how-much-does-it-cost-to-create-an-app-like-whatsapp/