Swift 4 - Firebase观察孩子改变并更新视图

时间:2017-12-01 09:15:34

标签: ios swift firebase firebase-realtime-database

我有一个复杂的问题需要解释,但我会尽可能地清楚地说明......

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

在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

我希望我已经能够解释所有事情......我已经尽力了解我...... 如果没有,请告诉我。

有人能帮帮我吗? 谢谢。

------ UPDATE 我正在观察这样的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)
            })
        })
    }
}

1 个答案:

答案 0 :(得分:0)

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

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

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