code

[SwiftUI] Firestore로 채팅 기능 구현하기

Lyla. 2023. 10. 26. 10:25

채팅 기능을 구현하던 중 마주한 문제를 적어봅니다. 한쪽에서는 메세지를 보내도 다른 한 기기에서는 메세지 업데이트가 안되는 상황이었습니다. 

 

상황: addSnapshotListener로 Firebase를 구독중인 ViewModel의 메서드를 만들어 놓고 구독중인 상황

 

ChatRoomStore의 프로퍼티

1) chatRoomList : 모든 채팅방을 가지고있음

2) messageList: 채팅방에서 해당하는 두 유저 사이의 Message만 배열로 가지고있음 

final class ChatRoomStore: ObservableObject {
    @Published var chatRoomList: [ChatRoom] = []
    @Published var messageList: [Message] = []
    }

 

func subscribeToChatRoomChanges() {
        
        let userCollection = Firestore.firestore().collection("ChatRoom")
        
        listenerObject = userCollection
            .addSnapshotListener { [weak self] (querySnapshot, error) in
                if let error = error {

addSnapshotListener를 통해서 chatRoomList를 업데이트 하니까 그 하위리스트인 Message도 같이 업데이트 되겠지?

 

라고 생각했으나 안됨!

 

 

해결방법

그러면, MessageList를 받아오는 addSnapshotListener를 self로 만들어봅시다!

 

조건

1) Timer 이용: 주기적으로 Firestore Database를 받아오게 함

2) 현재 기기상의 messageList와 Firestore상의 MessageList를 비교하여 다르면 기기상의 messageList를 갱신한다. 

  ※ 갱신된 messageList는 뷰를 그리는데 이용되므로, messageList의 갱신은 DispatchQueue.main.async를 통해 메인스레드에서 실행되도록 해야한다. 

 

func fetchMessage(myNickName: String, otherUserNickname: String) {
    var tempMessageList:[Message] = []
    self.isShowingChatLoading = true

    timer = Timer.scheduledTimer(withTimeInterval:  0.5, repeats: true) { timer in
    //경로 지정 후 값 받아오기
     userCollection
            .getDocuments { (querySnapshot, error) in
            //...
             for document in querySnapshot.documents {

             }
         }   
     DispatchQueue.main.async {
        if self.messageList != tempMessageList {
            self.messageList = tempMessageList
            tempMessageList=[]
            self.isShowingChatLoading = false
        }
        tempMessageList=[]
    }
}