1. Save messages with ‘send button’
  2. Fetch messages
  3. SnapshotListener on query
  4. Auto scrolling
  5. Save messages on both users

1. Save messages with ‘send button’

Send button is in customInputAccessoryView that you’ve made before. So you can addTarget to sendButton: handleSend.

You have a customInputView declared as a lazy var. you can easily access properties of customInputView.

Declare a collection for add Document

In Firebase, datas are saved as collection>document>collection>document ... so you can declare a collection, it’s kind of directory address.

        let collection = Firestore.firestore().collection("matches_messages").document(currentUserId).collection(match.uid)

Modify Message, model data form

You need to specify not only text, uid of sender, receiver. Also time the message sent is really matter.

import Firebase

struct Message {
    let text, fromId, toId: String
    let timestamp: Timestamp
    let isFromCurrentLoggedUser: Bool
}

You can decide isFromCurrentLoggedUser property when you save a message by checking fromId property in init function Message struct.

2. Fetch messages

To fetch messages, you need to set query first.

let query = Firestore.firestore().collection("matches_messages").document(currentUserId).collection(match.uid).order(by: "timestamp")

getDocuments

You could think just fetching messages is super easy by using getDocuments.

        query.getDocuments { (querySnapshot, err) in

            if let err = err {
                print("Failed to fetch messages", err)
                return
            }

            querySnapshot?.documents.forEach({ (documentSnapshot) in
                self.items.append(Message(dictionary: documentSnapshot.data()))
            })

            self.collectionView.reloadData()
        }

3. SnapshotListener on query

addSnapshotListener

But you have to use SnapshotListener to render messages right after send them. getDocuments only can fetch messages when you entered chatLogController.

        query.addSnapshotListener { (querySnapshot, err) in
            if let err = err {
                print("Failed to fetch messages", err)
                return
            }
            
            querySnapshot?.documentChanges.forEach({ (change) in
                if change.type == .added {
                    let dictionary = change.document.data()
                    self.items.append(.init(dictionary: dictionary))
                }
            })
            self.collectionView.reloadData()
            self.collectionView.scrollToItem(at: [0, self.items.count - 1], at: .bottom, animated: true)
        }

4. Auto scrolling

scrollToItem

In collectionViewController, there is a function for moving scroll of collections.

func scrollToItem(at indexPath: IndexPath, at scrollPosition: UICollectionView.ScrollPosition, animated: Bool)

Wha you’re going to do is scroll to the bottom. items got all cells so you can easily access to last cell using items array.

self.collectionView.scrollToItem(at: [0, self.items.count - 1], at: .bottom, animated: true)

So when you entered chatLogController or send a new message, you need to scroll to the bottom.

notificationCenter

NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardShow), name: UIResponder.keyboardDidShowNotification, object: nil)

I wanted to add UITapGestureRecognizer to dismiss keyboard when you tap collectionView. But it doesn’t work.

        collectionView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTapDismiss)))

    @objc fileprivate func handleTapDismiss() {
//        self.collectionView.endEditing(true)
//        self.view.endEditing(true)
    }

5. Save messages on both users

When you save messages using addDocument, you were saving only for current logged user. So receivers can’t see all the chat logs. So you need to save a message data both sides

태그: ,

카테고리:

업데이트:

댓글남기기