Firebase 更新 child 值正在删除 children

Firebase update child values is removing children

我正在尝试使用 Firebase 在我的社交媒体应用程序中处理关注和取消关注。我有一个标题为 "Follow" 的栏按钮项。点击时,它会检查当前的关注状态(在 viewDidLoad 中检索),并相应地调用 follow/unfollow 方法。 user 代表页面的所有者,currentUser 想要 follow/unfollow.

的人

意外行为:第二次关注用户时,您可以看到数据库中正确的 child 节点出现,然后消失。他们不应该消失。我已经刷新页面以确保节点实际上以某种方式被删除。它在每次应用程序启动后的第一次尝试中都能正常工作。

这是我的viewDidLoad(负责获取currentUserIsFollowing)。我怀疑问题出在这里:

override func viewDidLoad() {
    super.viewDidLoad()

    let userDogRef = Database.database().reference().child("users").child(user.uid!).child("dogs")

    let followingRef = Database.database().reference().child("users").child((Auth.auth().currentUser?.uid)!).child("following")

    followingRef.observeSingleEvent(of: .childAdded) { (snapshot) in
        if snapshot.value == nil {
            print("no following found")
            return
        }
        let value = snapshot.value as? NSDictionary
        let followingUserUID = String(describing: value!["uid"]!)
        if self.user.uid == followingUserUID {
            self.currentUserIsFollowing = true
            DispatchQueue.main.async {
                self.followBarButtonItem.title = "Unfollow"
            }
        }

    }
}

这是点击 Follow/Unfollow 按钮时调用的操作:

@IBAction func followUserButtonPressed(_ sender: Any) {
    if !currentUserIsFollowing {
        followUser()
        return
    }
    if currentUserIsFollowing {
        unfollowUser()
        return
    }
}

这里是 followUser() 方法:

fileprivate func followUser() {
    let followingRef = Database.database().reference().child("users").child((Auth.auth().currentUser?.uid)!).child("following")
    let followersRef = Database.database().reference().child("users").child(user.uid!).child("followers")

    followingRef.childByAutoId().updateChildValues(["uid": user.uid as Any]) { (error, ref) in
        if error != nil {
            print(String(describing: error?.localizedDescription))
        }
    }

    followersRef.childByAutoId().updateChildValues(["uid": Auth.auth().currentUser?.uid as Any]) { (error, ref) in
        if error != nil {
            print(String(describing: error?.localizedDescription))
        }
    }

}

这里是unfollowUser()方法:

fileprivate func unfollowUser() {
    let followingRef = Database.database().reference().child("users").child((Auth.auth().currentUser?.uid)!).child("following")
    let followersRef = Database.database().reference().child("users").child(user.uid!).child("followers")

    followingRef.observeSingleEvent(of: .childAdded, with: { (snapshot) in
        if snapshot.value == nil {
            print("no following found")
        }
        let value = snapshot.value as? NSDictionary
        let followingUserUID = String(describing: value!["uid"]!)
        if self.user.uid == followingUserUID {
            snapshot.ref.removeValue()
        }
    })

    followersRef.observeSingleEvent(of: .childAdded, with: { (snapshot) in
        if snapshot.value == nil {
            print("no followers found")
        }
        let value = snapshot.value as? NSDictionary
        let followerUserUID = String(describing: value!["uid"]!)
        if Auth.auth().currentUser?.uid == followerUserUID {
            snapshot.ref.removeValue()
        }
    })

}

这是我的 JSON 树的照片:

这里有很多事情要解压缩,但我尽力跟进并提出了解决方案。首先,创建一个处理关注和取消关注的函数,而不是拥有两个函数:

@IBAction func followUserButtonPressed(_ sender: Any) {
    followOrUnfollow()
}

在该函数中,听一次您需要的 child 的值。不要使用 childByAutoId,而是使用 uid 作为键,使用任何东西作为值。我刚刚使用了 true。这意味着您可以直接观察引用,而不必遍历所有 children 来寻找一个关注者。如果 child 的数据为 nil,那么用户还没有关注,因此更新数据库以关注。如果child的数据不为nil,则删除数据。

func followOrUnfollow() {
    let followingRef = Database.database().reference().child("users/\(Auth.auth().currentUser?.uid)!/following/\(user.uid!)")
    let followersRef = Database.database().reference().child("users/\(user.uid)!/followers/\(Auth.auth().currentUser?.uid)!")

    followingRef.observeSingleEvent(of: .value, with: { (snapshot) in
         if snapshot.value == nil {
            print("no following found")
            followingRef.updateChildValues([user.uid: "true"]) { (error, ref) in
                if error != nil {
                    print(String(describing: error?.localizedDescription))
                }
            }
        } else {
            print("unfollowing")
            snapshot.ref.removeValue()
        }
    })

    followersRef.observeSingleEvent(of: .value, with: { (snapshot) in
        if snapshot.value == nil {
            print("no followers found")
            followersRef.updateChildValues([Auth.auth().currentUser?.uid: "true"]) { (error, ref) in
                if error != nil {
                    print(String(describing: error?.localizedDescription))
                }
            }
        } else {
            print("unfollowing")
            snapshot.ref.removeValue()
        }
    })
}

现在可能会有一些语法错误,因为我正在盲目地研究这个,但这是我推荐的要点。您可能需要对此进行调整以满足您的需求。

我会 select Jen 的回答是正确的,但我想添加我的工作代码。我不得不做出一些改变来实现我的愿景。您不能将 snapshot.value 与 nil 进行比较,因此您应该使用 if snapshot.exists()。为了避免使用ref.updateChildValues()在参考点添加一个全新的child,我使用了.setValue("true")。这只是将新的 key-value 对添加到 ref 的 "following" 和 "followers" 节点。

func followOrUnfollow() {

    let followingRef = Database.database().reference().child("users/\(Auth.auth().currentUser!.uid)/following/\(self.user.uid!)")
    let followersRef = Database.database().reference().child("users/\(user.uid!)/followers/\(Auth.auth().currentUser!.uid)")

    followingRef.observeSingleEvent(of: .value, with: { (snapshot) in
        if !snapshot.exists() {
            print("no following found")
            followingRef.setValue("true") { (error, ref) in
                if error != nil {
                    print(String(describing: error?.localizedDescription))
                }

            }
        } else {
            print("unfollowing")
            snapshot.ref.removeValue()
        }
    })

    followersRef.observeSingleEvent(of: .value, with: { (snapshot) in
        if !snapshot.exists() {
            print("no followers found")
            followersRef.setValue("true") { (error, ref) in
                if error != nil {
                    print(String(describing: error?.localizedDescription))
                }
                DispatchQueue.main.async {
                    self.followBarButtonItem.title = "Unfollow"
                }
            }
        } else {
            print("unfollowing")
            snapshot.ref.removeValue()
            DispatchQueue.main.async {
                self.followBarButtonItem.title = "Follow"
            }
        }
    })
}

这是我的树的照片: