Hi,
Have just completed lesson 15 of the Chat App. thought everything was as good as the lesson had taught me but for the life of me, the dummy chats we built in the database are not showing up in my app!
I have triple checked the database, the database naming, the creation of the dummy chat & cross checked my code with the completed code from the course assets & I can’t find any differences? I have tried debugging but it seems once we get past the no errors and the snapshot isn’t empty check the snapshot can’t seem to unpack any chat even though its not empty but ends up no value?
My brain feels frazzled now, so I am reaching out in hope that I have missed something super simple to make me feel like a wally ha ha
Here is my DatabaseService()
// DatabaseService.swift
// ChatApp
//
// Created by Billie Blanchard on 07/09/2023.
//
import Foundation
import Contacts
import Firebase
import FirebaseStorage
class DatabaseService {
func getPlatformUsers(localContacts: [CNContact], completion: @escaping ([User]) -> Void) {
var platformUsers = [User]()
// Construct an array of string phone numbers to look up
var lookupPhoneNumbers = localContacts.map { contact in
// Turn the contact into a phone number string
return TextHelper.sanitizePhoneNumber(contact.phoneNumbers.first?.value.stringValue ?? "")
}
// Make sure that there are lookup numbers
guard lookupPhoneNumbers.count > 0 else {
// Callback
completion(platformUsers)
return
}
// Set database
let db = Firestore.firestore()
// Query database until no more phone numbers to query
while !lookupPhoneNumbers.isEmpty {
// Get the first 10 or < phone numbers to look up
let firstTenPhoneNumbers = Array(lookupPhoneNumbers.prefix(10))
// Remove the < 10 that we're looking up
lookupPhoneNumbers = Array(lookupPhoneNumbers.dropFirst(10))
let query = db.collection("users").whereField("phone", in: firstTenPhoneNumbers)
// Retrieve the users that already hold an account
query.getDocuments { snapshot, error in
// Check for errors
if error == nil && snapshot != nil {
// For each doc/user that was fetched, create a new user
for doc in snapshot!.documents {
if let user = try? doc.data(as: User.self) {
//Append to the platform users array
platformUsers.append(user)
}
}
// Check if we have more phone numbers to look up
// If not, we can call completion block
if lookupPhoneNumbers.isEmpty {
// Return the users with an account
completion(platformUsers)
}
}
}
}
}
func setUserProfile(firstname: String, lastName: String, image: UIImage?, completion: @escaping (Bool) -> Void) {
// Ensure user is logged in
guard AuthViewModel.isUserLoggedIn() != false else {
// User not logged in
return
}
// Get user's phone number
let userPhone = TextHelper.sanitizePhoneNumber(AuthViewModel.getLoggedInUserPhone())
// Get a reference to Firestore
let db = Firestore.firestore()
// Set the profile data
let doc = db.collection("users").document(AuthViewModel.getLoggedInUserId())
doc.setData(["firstname": firstname,
"lastname": lastName,
"phone": userPhone
])
// Check if image is passed through
if let image = image {
// Create storage reference
let storageRef = Storage.storage().reference()
// Turn our image into data
let imageData = image.jpegData(compressionQuality: 0.8)
// Check that we were able to convert it to data
guard imageData != nil else {
return
}
// Specify the file path and name
let path = "images/\(UUID().uuidString).jpg"
let fileRef = storageRef.child(path)
_ = fileRef.putData(imageData!, metadata: nil) { meta, error in
if error == nil && meta != nil {
// Get full URL to image
fileRef.downloadURL { url, error in
// Check for errors
if url != nil && error == nil {
// Set that image path to the profile
doc.setData(["photo": url!.absoluteString], merge: true) { error in
if error == nil {
// Success, notify user
completion(true)
}
}
} else {
// Unsuccesful in getting download of url for photo
completion(false)
}
}
} else {
// Upload was not successful, notify user
completion(false)
}
}
} else {
// No image was set
completion(true)
}
}
func checkUserProfile(completion: @escaping (Bool) -> Void) {
// Check that the user is logged in
guard AuthViewModel.isUserLoggedIn() != false else {
return
}
// Create firebase ref
let db = Firestore.firestore()
// Look for user
db.collection("users").document(AuthViewModel.getLoggedInUserId()).getDocument { snapshot, error in
// TODO: Keep the users profile data
if snapshot != nil && error == nil {
// Notify that profile exists
completion(snapshot!.exists)
} else {
// TODO: Look into using result type to indicate faliure vs profile exists
completion(false)
}
}
}
// MARK: - Chat Methods
/// This method returns all chat documents where the logged in user is a participant
/// If no chats then an empty chat array is returned
func getAllChats(completion: @escaping ([Chat]) -> Void) {
// Get a reference to the database
let db = Firestore.firestore()
// Perform a query against the chat collection for any chats where the user is a participant
let chatsQuery = db.collection("chats")
.whereField("participantids",
arrayContains: AuthViewModel.getLoggedInUserId())
chatsQuery.getDocuments{ snapshot, error in
// Check no errors have happened
if snapshot != nil && error == nil {
// Store the chats
var chats = [Chat]()
// Loop through all the returned chat documents
for doc in snapshot!.documents {
// Parse the data into Chat structures
let chat = try? doc.data(as: Chat.self)
// Add the chat into the chat array if not nil
if let chat = chat {
chats.append(chat)
}
}
// Return the data
completion(chats)
}
else {
// Errors exist
print("Error in database retrieval of chats")
}
}
}
/// This method returns all messages for a given chat
func getAllMessages(chat: Chat, completion: @escaping ([ChatMessage]) -> Void) {
// Check chat has a chat id & is not nil
guard chat.id != nil else {
// Can't fetch data - return empty chatMessage
completion([ChatMessage]())
return
}
// Get a reference to the database
let db = Firestore.firestore()
// Create the query
let msgsQuery = db.collection("chats")
.document(chat.id!)
.collection("msgs")
.order(by: "timestamp")
// Perform the query
msgsQuery.getDocuments { snapshot, error in
// Parse the data
// Check no errors exist
if snapshot != nil && error == nil {
// Loop through the msg documents & create ChatMessage instances
// Store the messages
var messages = [ChatMessage]()
for doc in snapshot!.documents {
let msg = try? doc.data(as: ChatMessage.self)
if let msg = msg {
// Add messages to message store
messages.append(msg)
}
}
// Return the results
return completion(messages)
}
else {
// Errors exist
print("Error in database retrieval of messages")
}
}
}
}
Thanks in advance!