Firestore 실시간 리스너에서 알림 도트를 구현해 보았습니다.

10673 단어 iOSFirebaseFirestore
실시간 리스너는 굉장한 기능인데 별로 사용도를 찾아내지 않고 단일 리퀘스트만 하고 있었습니다만, 조금 사용할 수 있는 여지가 있는 부분을 발견했으므로 시험해 보았습니다.

알림 점



SNS나 알림등의 탭상에 있는 알레입니다. 부정기 갱신된 기능이라도 보고 싶을 때에 봐주기 위한 도선이 되기 때문에 좋은 것입니다.
읽지 않거나 매번 페치하는 것보다 실시간 업데이트하는 것이 더 재미 있기 때문에 실시간으로 데이터를 동기화하여 알림 점을 표시하려고합니다 🐞

사양


  • 알림 목록으로 전환하는 탭이있는 앱
  • 알림에 읽지 않은 경우 알림 탭에 알림 점을 표시합니다
  • 공지사항 정렬은 항상 최신순

  • 구현 방법



    읽지 않은 판정



    읽지 않은지의 판정은 취득된 최신 1건의 문서 ID와 읽은 것으로 간주된 로컬에 보존되고 있는 문서 ID로 판단하는 심플한 것입니다.
    public struct UnreadState {
        private(set) var latestLocalId: String?
        private(set) var latestRemoteId: String?
    
        public var hasUnread: Bool {
            guard let local = latestLocalId,
                let remote = latestRemoteId else {
                return false
            }
            return local != remote
        }
    
        // ...
    }
    

    공지사항 모음집 만들기


    notifications/{notificationId}

    Firestore 실시간 리스너로 데이터 모니터링



    공지 컬렉션의 최신 1건을 듣기
    Firestore.firestore()
        .collection("notifications")
        .order(by: "createdAt", descending: true)
        .limit(to: 1)
        .addSnapshotListener({ (snapshot, _) in
            // 最新1件目のドキュメントID
            let latestRemoteId = snapshot?.documents.first?.documentID
        })
    }
    

    로컬 읽지 않음은 우선 UserDefaults



    통지 일람으로 천이했을 때에 최신의 1건의 문서 ID를 기독으로 간주해 보존한다.
    // お知らせ一覧を取得してきた想定
    let notificationId = notifications.first?.id
    userDefaults.set(notificationId, forKey: .lastReadNotificationId)
    

    알림 일람으로 전환시 단일 요청으로 취득한 최신 1건을 보존한다.

    이와 같이 플랫하게 저장해 버리면 복수 계정의 미독을 관리할 수 없지만 여기에서는 몰랐던 것으로 한다.

    View 업데이트


    // 通知ドットView
    let notificationDot: DotView = .init()
    
    // state is Observable<UnreadState>
    state
        .map { $0.hasUnread }
        .distinctUntilChanged()
        .bind(to: Binder(self) { me, hasUnread in
            me.notificationDot.isHidden = !hasUnread
        })
        .disposed(by: disposeBag)
    

    RxSwift를 이용하고 있습니다만 어떠한 방법으로 View에 변경을 전합니다.

    알림 점 View



    마무리에 통지 닷 View에는 좋은 느낌의 출현 애니메이션을 구현해 줍니다.
    class DotView: UIView {
    
        init() {
            super.init(frame: .init(x: 0, y: 0, width: 5, height: 5))
            backgroundColor = SPColor.badge
            layer.cornerRadius = bounds.midX
            isHidden = true
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override var isHidden: Bool {
            didSet {
                guard oldValue != self.isHidden else {
                    return
                }
                if !self.isHidden {
                    appearAnimation()
                }
            }
        }
    
        private func appearAnimation() {
            self.transform = CGAffineTransform(scaleX: 0, y: 0)
            UIView.animate(
                withDuration: 0.6,
                delay: 0,
                options: .curveEaseInOut,
                animations: { self.transform = CGAffineTransform.identity }
            )
        }
    }
    
    isHidden 프로퍼티를 오버라이드(override) 해 출현시에 확대 애니메이션을 추가했습니다.



    도파민이 분비됩니다 😇

    결론



    이대로 실운용이라고 줄지어 순서의 변경이나 미독수 카운트등에 의해 파탄하는 미래가 보입니다만, 비교적 최소한 실장으로 부족한 케이스도 적지 않을까 생각합니다. 이 기능을 응용하여 업데이트 플래그에 이용할 수도 있습니다.

    좋은 웹페이지 즐겨찾기