정확히는 ListenerRegistration로 파베에서 지원해주는 함수이다.
FireStore에서 특정 컬렉션 데이터가 변경되는것을 실시간으로 관찰하고 로직을 실행한다
다른 유저들이 A 사용자를 평가한뒤, A사용자의 평가점수를 실시간으로 보고싶을때 유용하다.
아래 짤을보면 "김지훈"이라는 사람의 "만족해요"점수가 실시간으로 올라간다.
굳이 일일이 평가완료 알림을 클릭않아도된다.
ReviewScoreViewModel이라는 ViewModel에 listener를 추가해준뒤 listenForReviewUpdates메소드에 listener를 적용시킨다
import FirebaseFirestore
class ReviewScoreViewModel: ObservableObject {
@Published var mannerScore: Int = 0
@Published var review0: Int = 0
@Published var review1: Int = 0
@Published var review2: Int = 0
let db = Firestore.firestore()
let userManager = UserManager.shared
var listener: ListenerRegistration?
}
extension ReviewScoreViewModel {
func listenForReviewUpdates(userId: String){
//기존 리스너 제거
listener?.remove()
// 특정 사용자의 리뷰 데이터에 대한 리스너 설정
listener = db.collection("User").document(userId).addSnapshotListener { documentSnapshot, error in
guard let document = documentSnapshot else {
print("Firestore error: \(error?.localizedDescription ?? "No error description")")
return
}
// reviews 데이터가 업데이트 되면 점수 재정의 및 mannerScore 재계산
if let reviews = document.data()?["reviews"] as? [Int], reviews.count == 3 {
self.updateReview(reviews: reviews)
}
}
}
}
extension ReviewScoreViewModel {
func updateReview(reviews: [Int]) {
if reviews[0] == 0 && reviews[1] == 0 && reviews[2] == 0{
self.mannerScore = -1
} else {
self.review0 = Int(reviews[0])
self.review1 = Int(reviews[1])
self.review2 = Int(reviews[2])
self.mannerScore = Int((Double(reviews[0] * 3)) / Double(((reviews[0] * 3) + (reviews[1] * 2) + (reviews[2] * 1))) * 100)
}
}
}
ReviewScoreView가 나타날때 listenForReviewUpdates메소드를 실행시키면 실시간으로 데이터가 변경된걸 볼 수 있다.
import SwiftUI
struct ReviewScoreView: View {
@StateObject var viewModel = ReviewScoreViewModel()
var otherUser: UserModel?
var body: some View {
VStack(spacing: 5) {
Text("\(viewModel.review0)")
.font(.system(size: 17, weight: .semibold))
}
.onAppear {
if let otherUser = otherUser{
viewModel.listenForReviewUpdates(userId: otherUser.id ?? "")
} else if let currentUser = viewModel.userManager.user {
viewModel.listenForReviewUpdates(userId: currentUser.id ?? "")
}
}
}
}