【问题标题】:Firebase update child values is removing childrenFirebase 更新子值正在删除子项
【发布时间】:2018-03-06 22:22:21
【问题描述】:

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

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

这是我的 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"
            }
        }

    }
}

这是点击关注/取消关注按钮时调用的操作:

@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 树的照片:

【问题讨论】:

    标签: ios json swift firebase uibarbuttonitem


    【解决方案1】:

    这里有很多事情要解压,但我尽我所能跟进并提出解决方案。其一,与其拥有两个函数,不如创建一个单独的函数来处理关注和取消关注:

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

    在那个函数中,听一次你需要的孩子的价值。不要使用childByAutoId,而是使用uid 作为键和任何值作为值。我刚刚使用true。这意味着您可以直接观察引用,而不必遍历所有子级来寻找一个追随者。如果孩子的数据为零,那么用户还没有关注,所以数据库更新为关注。如果孩子的数据不为零,则删除数据。

    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()
            }
        })
    }
    

    现在可能存在一些语法错误,因为我正在盲目地处理这个问题,但这是我建议的要点。您可能需要对此进行调整以满足您的需求。

    【讨论】:

    • 我必须进行一些更改才能使其正常工作,但这仍然不是我想象的那样。正如您目前所写的那样,您在创建引用时在字符串插值期间添加了几个感叹号。我还必须将 if snapshot.value == nil 检查更改为 if !snapshot.exists() 因为 nil 与 Any 的比较失败。
    • 另一件事是 JSON 树看起来不像预期的那样。现在进入 users/currentUser.uid/following/user.uid/(user.uid:true)。我希望在没有重复孩子的情况下构建它。即用户/currentUser.uid/following/(user.uid:true)。当我尝试这个时,每个新用户都会覆盖最后一个。我希望这是有道理的。我怎样才能得到想要的结果?还是我应该保持原样?
    【解决方案2】:

    我会选择 Jen 的答案作为正确答案,但我想添加我的工作代码。我必须做出一些改变来实现我的愿景。您不能将 snapshot.value 与 nil 进行比较,因此您应该使用 if snapshot.exists()。为了避免使用ref.updateChildValues() 在参考点添加一个全新的孩子,我使用了.setValue("true")。这只是将一个新的键值对添加到 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"
                }
            }
        })
    }
    

    这是我的树的图片:

    【讨论】:

      猜你喜欢
      • 2018-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多