-
[SwiftUI] Firestore로 채팅 기능 구현하기code 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=[] } }
'code' 카테고리의 다른 글
URLSession: 서버와 소통하는 주체, Json Decode (0) 2024.02.20 [Swift] Realm 스레딩 이용시 주의사항 - Realm은 하나의 스레드에서 작업이 이루어져야 한다 (0) 2023.03.17 지정생성자vs편의생성자, 클래스와 인스턴스의 메모리 구조 차이 (0) 2023.03.15 리스트에 자료 추가하기 (0) 2022.10.20 cvs 파일 python에서 쓰기 (0) 2022.10.20