
리스너를 알아봅시다
채팅같은 거 구현할 때 씀
UserManager에서 Listener를 추가해주는 메소드를 작성함

completion이 됐을 때 products를 @escaping으로 넘겨주고!

뷰모델에서 Listener추가해주는 메소드 다시 구성해줌!

그리고 view가 onAppear될 때 Listener를 추가해주면~
되는데 .onAppear가 딱 처음 등장할때만 리스너를 추가해줘야함!

변수하나 @State로 파서 처음 떴을 때만 listener가 추가되게 해줬다!
크~!!~!~!~!~!
데이터들 바로바로 적용되는 거 볼 수 있음!!
listener를 없애는 방법도 알아야겠죠
채팅방에 들어갔다가 나왔을 때는 더 이상 필요가 없을테니까!!


요런식으로~
func addListenerForAllUserFavoriteProducts(userId: String, completion: @escaping (_ products: [UserFavoriteProduct]) -> Void) {
self.userFavoriteProductsListener = userFavoriteProductCollection(userId: userId).addSnapshotListener { querySnapshot, error in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
let products: [UserFavoriteProduct] = documents.compactMap({ try? $0.data(as: UserFavoriteProduct.self)})
completion(products)
querySnapshot?.documentChanges.forEach { diff in
if (diff.type == .added) {
print("New products: \(diff.document.data())")
}
if (diff.type == .modified) {
print("Modified products: \(diff.document.data())")
}
if (diff.type == .removed) {
print("Removed products: \(diff.document.data())")
}
}
}
}
그래서 변한 걸 어떤건지에 대한 것들도
요렇게 if 문으로 나눌 수 있음

요 리스너를 publisher로 바꿔주는 것도 가능함!!
func addListenerForAllUserFavoriteProducts(userId: String) -> AnyPublisher<[UserFavoriteProduct], Error> {
let publisher = PassthroughSubject<[UserFavoriteProduct], Error>()
self.userFavoriteProductsListener = userFavoriteProductCollection(userId: userId).addSnapshotListener { querySnapshot, error in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
let products: [UserFavoriteProduct] = documents.compactMap({ try? $0.data(as: UserFavoriteProduct.self)})
publisher.send(products)
}
return publisher.eraseToAnyPublisher()
}
earaseToAnyPublisher로 코드를 더 제네릭 하게 만들어줄 수도 있겠죠

실제로 교체해주면 뿜~!
combine으로 바꼈습니다~~
더 제네릭하게 바꿔볼까요

요렇게!

요렇게!!
그리고 아까 onAppear일 때 체크하려고 Bool값 만들어줬었잖음
그것도 바꿔봅시다
struct OnFirstAppearViewModifier: ViewModifier {
@State private var didAppear: Bool = false
let perform: (() -> Void)?
func body(content: Content) -> some View {
content
.onAppear {
if !didAppear {
perform?()
didAppear = true
}
}
}
}
extension View {
func onFirestAppear(perform: (() -> Void)?) -> some View {
modifier(OnFirstAppearViewModifier(perform: perform))
}
}
캬~
이게 ViewModifier의 힘이구나!!!