[SiwftUI] listener/ListenerRegistration/리스너

힐링힐링·2024년 4월 5일
0

SwiftUI

목록 보기
13/14

listener란?

정확히는 ListenerRegistration로 파베에서 지원해주는 함수이다.
FireStore에서 특정 컬렉션 데이터가 변경되는것을 실시간으로 관찰하고 로직을 실행한다

listener를 왜 사용하나?

다른 유저들이 A 사용자를 평가한뒤, A사용자의 평가점수를 실시간으로 보고싶을때 유용하다.

아래 짤을보면 "김지훈"이라는 사람의 "만족해요"점수가 실시간으로 올라간다.
굳이 일일이 평가완료 알림을 클릭않아도된다.

코드

ViewModel

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)
        }
    }
}

View

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 ?? "")
            }
            
        }
    }
}
profile
블로그 이전합니다 https://james-kim-tech.tistory.com/

0개의 댓글