Having Proper Message Functionality with Parse, UIKit and MessageKit

For my iOS Social Media App project, I am currently working on the Direct Messaging feature of the app. As of making this post, I have the basic functionality working where you can send messages to other users in the app. However, there are a few issues I am experiencing.

1.) Being able to see the other user’s texts and replies. I can send a message to the user but said user won’t be able to see it and vice versa for some reason I haven’t been able to fetch and load chat history properly.

2.) The chats don’t have their own unique messages. If I send a message to one user, it shows up in my chats with other users as well rather than each chat having its own unique messages.

They both seem to be issues related to fetching saved data from my Parse Cloud. The messages are saved properly to the cloud but fetching them and displaying them seems to be the issue.

Here is my code associated with Messaging:

import UIKit
import MessageKit
import Parse

class DirectMessagingViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{   var otherUsers = [PFUser]()
    var currentUser: PFUser!
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return otherUsers.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = otherUsers[indexPath.row].username
        cell.accessoryType = .disclosureIndicator
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        // Show chat messages
        let vc = ChatViewController()
        vc.title = otherUsers[indexPath.row].username
        navigationController?.pushViewController(vc, animated: true)
    }
    
    @IBOutlet var myTable: UITableView!
    
    override func viewDidLoad()
       {
           super.viewDidLoad()
           
           myTable.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
           myTable.delegate = self
           myTable.dataSource = self
           
           // Get current user
           currentUser = PFUser.current()
           
           // Query for other users
           let query = PFUser.query()
           query?.whereKey("objectId", notEqualTo: currentUser.objectId!)
           query?.findObjectsInBackground(block: { (users, error) in
               if let users = users as? [PFUser] {
                   self.otherUsers = users
                   self.myTable.reloadData()
               } else {
                   print("Error querying for users: \(error?.localizedDescription ?? "")")
               }
           })
       }
   }
import UIKit
import MessageKit
import InputBarAccessoryView
import Parse

struct Message: MessageType
{
    var sender: SenderType
    var messageId: String
    var sentDate: Date
    var kind: MessageKind
}

class ChatViewController: MessagesViewController, MessagesDataSource, MessagesLayoutDelegate, MessagesDisplayDelegate, InputBarAccessoryViewDelegate
{
    let currentUser = PFUser.current()!
    var otherUser: PFUser!
    var messages = [MessageType]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set up the other user
        let query = PFUser.query()
        query?.whereKey("objectId", notEqualTo: currentUser.objectId!)
        query?.findObjectsInBackground(block: { (objects, error) in
            if let users = objects as? [PFUser], let user = users.first {
                self.otherUser = user
                
                // Retrieve previous messages from Parse
                let messageQuery = PFQuery(className: "Message")
                messageQuery.whereKey("sender", equalTo: self.currentUser)
                messageQuery.whereKey("recipient", equalTo: self.otherUser!)
                let recipientQuery = PFQuery(className: "Message")
                recipientQuery.whereKey("sender", equalTo: self.otherUser!)
                recipientQuery.whereKey("recipient", equalTo: self.currentUser)
                let query = PFQuery.orQuery(withSubqueries: [messageQuery, recipientQuery])
                query.findObjectsInBackground { (objects, error) in
                    if let messages = objects {
                        for message in messages {
                            let sender = message["sender"] as! PFUser
                            let text = message["text"] as! String
                            let sentDate = message.createdAt!
                            let messageKind = MessageKind.text(text)
                            let messageSender: Sender
                            do {
                                try sender.fetchIfNeeded()
                                messageSender = Sender(senderId: sender.objectId!, displayName: sender.username ?? "")
                            } catch {
                                messageSender = Sender(senderId: sender.objectId!, displayName: "Unknown")
                                print("Error fetching sender: \(error.localizedDescription)")
                            }
                            let message = Message(sender: messageSender, messageId: message.objectId!, sentDate: sentDate, kind: messageKind)
                            self.messages.append(message)
                            print("Fetched previous messages!")
                        }
                        
                        self.messagesCollectionView.reloadData()
                        self.messagesCollectionView.scrollToLastItem(animated: false)
                    }
                }
            }
        })
        
        // Configure the messages collection view and input bar
        messagesCollectionView.messagesDataSource = self
        messagesCollectionView.messagesLayoutDelegate = self
        messagesCollectionView.messagesDisplayDelegate = self
        messageInputBar.delegate = self
        messageInputBar.inputTextView.placeholder = "Type a message..."
        messageInputBar.sendButton.setTitle("Send", for: .normal)
        messageInputBar.sendButton.setTitleColor(view.tintColor, for: .normal)
        messageInputBar.sendButton.addTarget(self, action: #selector(sendButtonPressed), for: .touchUpInside)
    }
    
    func currentSender() -> SenderType
    {
        return Sender(senderId: currentUser.objectId!, displayName: currentUser.username ?? "")
    }
    
    func numberOfSections(in messagesCollectionView: MessagesCollectionView) -> Int
    {
        return messages.count
    }
    
    func messageForItem(at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageType
    {
        return messages[indexPath.section]
    }
    
    @objc func sendButtonPressed() {
        let messageText = messageInputBar.inputTextView.text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !messageText.isEmpty else {
            return
        }
        
        let message = Message(sender: currentSender(), messageId: UUID().uuidString, sentDate: Date(), kind: .text(messageText))
        messages.append(message)
        messageInputBar.inputTextView.text = ""
        messagesCollectionView.reloadData()
        messagesCollectionView.scrollToLastItem(animated: true)
        print("Message sent!")
        
        // Save the message to Parse
        let parseMessage = PFObject(className: "Message")
        parseMessage["sender"] = currentUser
        parseMessage["recipient"] = otherUser
        parseMessage["text"] = messageText
        parseMessage.saveInBackground { (success, error) in
            if success {
                print("Message saved!")
            } else if let error = error {
                print("Error saving message: \(error.localizedDescription)")
            }
        }
    }
    
    func inputBar(_ inputBar: InputBarAccessoryView, textViewTextDidChangeTo text: String)
    {
        if text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
        {
            inputBar.sendButton.isEnabled = false
        } else
        {
            inputBar.sendButton.isEnabled = true
        }
    }
    
    func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith text: String)
    {
        sendButtonPressed()
    }
}

The DirectMessageViewController() loads all the users you can chat with and displays the conversation with a user when you tap on that user. The ChatViewController() is what handles the functionality regarding sending messages, saving them to the Parse Cloud, and fetching them. All help would be greatly appreciated!