Swift Firebase观察.childAdded对现有项目而不是新项目的反应

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift Firebase观察.childAdded对现有项目而不是新项目的反应相关的知识,希望对你有一定的参考价值。

我有一个裁判,我只想在添加新项目时收听(它位于下面的viewWillAppear中)。添加新项目时,将显示newItemsButton。如果没有任何新内容添加到数据库中已有的内容,则该按钮不应出现。

问题是观察者一开始观察,即使没有添加任何新内容,newItemButton也会出现。 我在做什么错?

db:

-posts
   -postId_1
   -postId_2
   -postId_3

代码:

var startKey: String?
let postsRef = Database.database().reference().child("posts")
let postsObserverRef = Database.database().reference().child("posts")

override func viewDidLoad() {
    super.viewDidLoad()

    paginate()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    listenForNewItems()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    postsObserverRef.removeAllObservers()
}

func listenForNewItems() {

    postsObserverRef.observe(.childAdded) { (snapshot) in

        let postId = snapshot.key
        let isContained = self.dataSource.contains { $0.postId == postId }

        if !isContained {

            // show newItemsButton
        }
    }
}

func paginate() {

    if startKey == nil {

        postsRef.queryOrderedByKey().queryLimited(toLast: 20)
            .observeSingleEvent(of: .value, with: { (snapshot) in
            // fill datasource
        })

    } else {

        postsRef.queryOrderedByKey().queryEnding(atValue: startKey).queryLimited(toLast: 21)
            .observeSingleEvent(of: .value, with: { (snapshot) in
            // fill datasource
        })
    }
}
答案

阅读完之后,无论如何,.observe(.childAdded)似乎总是会触发至少一次。我对代码做了一些调整。这似乎是聆听新项目的不必要的长途之路,但这肯定可以消除我最初遇到的问题。我会接受任何更好的答案。

var lastPostId: String?
let postsObserverRef = Database.database().reference().child("posts")

override func viewDidLoad() {
    super.viewDidLoad()

    paginate()
    getLastPostIdForNewItems()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

     // I added this 1 sec wait here only to make sure the getLastPostIdForNewItems() in viewDidLoad finishes first. When switching tabs or pushing on/off child vcs the 1 sec won't make any difference
     DispatchQueue.main.asyncAfter(deadline: .now() + 1) {

        self.listenForNewItems(key: self.lastPostId)
     }
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    removeNewItemsObserver()
}

func getLastPostIdForNewItems() {

    postsObserverRef.queryLimited(toLast: 1).observeSingleEvent(of: .value) { (snapshot) in

        guard let childSnapshot = snapshot.children.allObjects.first as? DataSnapshot else {
            return
        }

        guard let dict = childSnapshot.value as? [String: Any] else { return }
        guard let lastPostId = dict["postId"] as? String else { return }

        self.lastPostId = lastPostId
        self.listenForNewItems(key: lastPostId)
    }
}

func listenForNewItems(key: String?) {

    if let lastPostId = key {

        postsObserverRef
            .queryOrderedByKey()
            .queryStarting(atValue: lastPostId)
            .observe(.childAdded) { (snapshot) in

                var postIds = [String]()

                if let dict = snapshot.value as? [String: Any], let postId = dict["postId"] as? String {

                    postIds.append(postId)
                }

                DispatchQueue.main.asyncAfter(deadline: .now() + 0.005) {

                    guard let lastPostId = postIds.last else { return }

                    let isContained = self.dataSource.contains { $0.postId == lastPostId }

                    if !isContained {

                        self.lastPostId = lastPostId
                        // showNewItemsButton
                    }
                }
        }

    } else {

        postsObserverRef.observe(.childAdded) { (snapshot) in

                var postIds = [String]()

                if let dict = snapshot.value as? [String: Any], let postId = dict["postId"] as? String {

                    postIds.append(postId)
                }

                DispatchQueue.main.asyncAfter(deadline: .now() + 0.005) {

                    guard let lastPostId = postIds.last else { return }

                    let isContained = self.dataSource.contains { $0.postId == lastPostId }

                    if !isContained {

                        self.lastPostId = lastPostId
                        // showNewItemsButton
                    }
                }
        }
    }
}

func removeNewItemsObserver() {

    if let lastPostId = lastPostId {

        postsObserverRef
            .queryOrderedByKey()
            .queryStarting(atValue: lastPostId)
            .removeAllObservers()

    } else {

        postsObserverRef.removeAllObservers()
    }
}

以上是关于Swift Firebase观察.childAdded对现有项目而不是新项目的反应的主要内容,如果未能解决你的问题,请参考以下文章

使用 Firebase 观察数据更新 UI (Swift)

Swift -Firebase 可以同时发布和观察

Swift,FIrebase - 无法通过 removeAllObservers 删除观察者

Swift:如果孩子的观察者被移除,则不会调用 Firebase 身份验证观察者

Swift 中的完成处理程序 Firebase 观察者

swift FireBase从数据库中观察/接收