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=[]
}
}