【问题标题】:Swift 4 - Firebase observe child changed and update the viewSwift 4 - Firebase 观察孩子改变并更新视图
【发布时间】:2017-12-01 09:15:34
【问题描述】:

我有一个有点复杂的问题要解释,但我会尽量说清楚......

我正在从 firebase 检索相同的值。具体来说,我有一个 Post 类和一个 User 类。 所以我的firebase结构的一部分是这样的:

在 myPost 中,我拥有与用户关联的所有 postId。 当视图加载时,我从 myPosts 获取与用户关联的所有 postID,并从他们那里获取来自 Posts 的所有帖子,然后在视图中显示它们。

这里是我用来获取帖子的详细功能:

var FEED_REF = Database.database().reference().child("myPosts")
func observeFeed(withUserId id: String, kPagination: Int, loadMore: Bool, postCount: Int? = 0, completion: @escaping (Post, FirebaseUser) -> Void, isHiddenIndicator:  @escaping (_ isHiddenIndicator: Bool?) -> Void, isEmpty: @escaping () -> Void) {
    FEED_REF.observeSingleEvent(of: .value) { (snapshot) in
        if !snapshot.hasChild(id) {
            isEmpty()
            return
        }
    }
    let query = FEED_REF.child(id).queryOrdered(byChild: "timestamp").queryLimited(toLast: UInt(kPagination))
    query.observeSingleEvent(of: .value, with: {
        snapshot in
        print("Got Snap in feed Observer")
        var items = snapshot.children.allObjects
        if loadMore {
            if items.count <= postCount! {
                isHiddenIndicator(true)
                return
            }
            items.removeLast(postCount!)
        }
        let myGroup = DispatchGroup()
        var results = Array(repeating: (Post(), FirebaseUser()), count: items.count)
        for (index, item) in (items as! [DataSnapshot]).enumerated() {
            myGroup.enter()
            Api.Post.observePost(withId: item.key, completion: { (post) in
                Api.User.observeUser(withId: post.uid, completion: { (user) in
                    results[index] = (post, user)
                    myGroup.leave()
                })
            })
        }
        myGroup.notify(queue: .main) {
            for result in results {
                completion(result.0, result.1)
            }
        }
    })
}

这里是观察帖子的功能:

 let POSTS_REF = Database.database().reference().child("Posts")

 func observePost(withId id: String, completion: @escaping (Post) -> Void) {
    POSTS_REF.child(id).observeSingleEvent(of: .value, with: {
        snapshot in
        if let dict = snapshot.value as? [String: Any] {
            let post = Post.getPost(dictionary: dict, key: snapshot.key)
            completion(post)
        }
    })
}

这里是观察用户的功能:

let USER_REF = Database.database().reference().child("Users")

func observeUser(withId uid: String, completion: @escaping(FirebaseUser) -> Void) {
    USER_REF.child(uid).observeSingleEvent(of: .value) { (snapshot) in
        if let dict = snapshot.value as? [String:Any] {
            let user = FirebaseUser.getUser(dictionary: dict, key: snapshot.key)
            completion(user)
        }
    }
}

在我的 viewDidLoad 中,我调用这个函数来更新视图:

func loadPosts() {
    activityIndicatorHome.startAnimating()
    guard let currentUserId = Api.User.CURRENT_USER?.uid else {return}
    Api.Feed.observeFeed(withUserId: currentUserId, kPagination: kPagination, loadMore: false, completion: { (post, user) in
        print("1")
        self.posts.insert(post, at: 0)
        self.users.insert(user, at: 0)
        self.tableView.reloadData()
        self.refreshControl.endRefreshing()
        self.activityIndicatorHome.stopAnimating()
    }, isHiddenIndicator: { (bool) in
        print("2")

    }) {
        print("3")
        self.activityIndicatorHome.stopAnimating()
        self.emptyTableViewDefaultText()
        self.tableView.reloadData()
        self.refreshControl.endRefreshing()
    }

如果没有变化,一切正常。 我现在要做的是观察变化。 这意味着如果用户添加或删除帖子,我想调用 loadPosts() 并更新视图。

我试过用这个:

    var MYPOSTS_REF = Database.database().reference().child("myPosts")
   func getMyPostInHome(userId: String, completion: @escaping () -> Void, isEmpty: @escaping () -> Void) {
    MYPOSTS_REF.observeSingleEvent(of: .value) { (snapshot) in
        if !snapshot.hasChild(userId) {
            isEmpty()
            return
        }
    }
    MYPOSTS_REF.child(userId).observe(.childChanged) { (snapshot) in
        //get the Added/Removed post id here
    }
}

但我似乎无法获取帖子 ID

我希望我已经能够解释一切......我已经尽力做到尽可能清楚...... 如果没有,请告诉我。

有人可以帮我吗? 谢谢。

-----更新 我正在观察 childAdded 像这样

func observePostAdded(userId: String, completion: @escaping (Post, FirebaseUser) -> Void) {
    MYPOSTS_REF.child(userId).observeSingleEvent(of: .childAdded) { (snapshot) in
        let key = snapshot.key
        print("KEY \(key)")
        Api.Post.getMyPosts(withId: key, completion: { (post) in
            Api.User.observeUser(withId: post.uid, completion: { (user) in
                completion(post, user)
            })
        })
    }
}

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    您正在观察子节点的变化,因此如果添加或删除任何帖子,它将不会执行。为此,您必须分别使用.childAdded.childRemoved

    还有一个 .childValue 观察者类型,它只会在每次添加/删除/修改任何节点时执行。

    您可以在此处查看带有相关信息的 firebase 文档: Firebase - Working with Lists of Data on iOS

    【讨论】:

    • 感谢您的回答。我设法通过使用 .childAdded 或 .childRemoved 来执行它。问题是它多次返回该值。所以基本上我第一次添加帖子时它可以工作,但第二次它会添加两倍相同的值,第三次添加 3 次等等......老实说,我不明白为什么......
    • 我正在使用这个:MYPOSTS_REF.child(userId).observeSingleEvent(of: .childAdded) 和前两个函数来获取帖子和用户
    • 您能否显示有关您所做更改的更新代码?
    • 有人可以添加示例代码片段吗,我无法让我的 .childchanged 观察者调用,但一切都符合要求!?
    猜你喜欢
    • 2019-07-23
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多