Ios Firebase更新子值正在删除子项

Ios Firebase更新子值正在删除子项,ios,json,swift,firebase,uibarbuttonitem,Ios,Json,Swift,Firebase,Uibarbuttonitem,我正在尝试使用Firebase在我的社交媒体应用程序中处理跟踪和取消跟踪。我有一个标题为“跟随”的酒吧按钮项目。点击时,它检查当前的跟随状态(在viewDidLoad中检索),并相应地调用跟随/取消跟随方法user表示页面的所有者,以及currentUser希望跟踪/取消跟踪的人 意外行为:第二次跟踪用户时,可以看到数据库中正确的子节点出现,然后消失。它们不应该消失。我刷新了页面,以确保节点实际上以某种方式被删除。它在每次应用程序启动后的第一次尝试中都能正常工作 这是我的viewDidLoad(

我正在尝试使用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))
        }
    }

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

}
以下是
unfollowUser()
方法:

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

}
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()
}
在这个函数中,听一次你需要的孩子的价值观。不要使用
childByAutoId
,而是使用
uid
作为键,使用任何内容作为值。我刚刚用了
true
。这意味着您可以直接观察引用,而不必遍历所有子对象来寻找一个跟随者。如果子对象的数据为nil,则用户尚未跟踪,因此数据库将更新为跟踪。如果子项的数据不是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()
        }
    })
}

现在可能会有一些语法错误,因为我是盲目的,但这是我建议的要点。您可能需要对此进行调整以满足您的需要。

我将选择Jen的答案作为正确答案,但我想添加我的工作代码。我必须做出一些改变来实现我的愿景。无法将snapshot.value与nil进行比较,因此如果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"
            }
        }
    })
}
这是我的树的照片:

我必须做出一些改变才能让它正常工作,但这仍然不是我想象的那样。正如您目前所写的,在创建引用时,在字符串插值过程中添加了几个感叹号。我还必须将if snapshot.value==nil检查更改为if!snapshot.exists()是因为将nil与Any进行比较失败。另一个原因是JSON树的外观与预期不符。现在转到users/currentUser.uid/following/user.uid/(user.uid:true)。我希望在没有复制孩子的情况下构建它。i、 e.users/currentUser.uid/following/(user.uid:true)。当我尝试这样做时,每个新用户都会覆盖上一个用户。我希望这是有道理的。我怎样才能得到想要的结果?还是我应该保持原样?