输入一个子节点以获取进入另一个子节点所需的信息

Posted

技术标签:

【中文标题】输入一个子节点以获取进入另一个子节点所需的信息【英文标题】:Enter a child node to get required information to enter another child node 【发布时间】:2019-03-15 18:58:28 【问题描述】:

我正在尝试获取写入警报子节点中的 autoId 并将其转换为字符串,以便从问题节点中获取此 autoId 以获取其中的信息 - 我的代码运行但不打印/工作

(当前用户 autoId 是 alert 节点的第一个子节点,userId 是来自“objectId”/questions 的第二个子节点的字符串)。这是我的代码:

@IBOutlet weak var statementAnswered: UILabel
@IBOutlet weak var number1Label: UIButton!
@IBOutlet weak var number2Label: UIButton!
@IBOutlet weak var number3Label: UIButton!
@IBOutlet weak var number4Label: UIButton!

 guard let currentUser = Auth.auth().currentUser?.uid else  return 
 let ref = Database.database().reference()

    //enter alert node to get the new Id under the current user node
    let userRef = ref.child("alert").child(currentUser)
    userRef.observe(.childAdded, with:  (snapshot) in
        let uniqueKey = snapshot.key
        print(uniqueKey)
        guard let senderDetails = snapshot.childSnapshot(forPath: "from").value as? String else  return 
        guard let userID = snapshot.childSnapshot(forPath: "objectID").value as? String else  return 
        print(senderDetails)
        print(userID)

        let questionNotification = ref.child("questions").child(senderDetails).child(userID)
        questionNotification.observeSingleEvent(of: .value, with:  (snapshot) in
            let value = snapshot.value as? NSDictionary
            let statement = value?["statement"] as! String
            let number1 = value?["number 1"] as! String
            let number2 = value?["number 2"] as! String
            let number3 = value?["number 3"] as! String
            let number4 = value?["number 4"] as! String
            print(statement)
            print(number1)
            print(number2)
            print(number3)
            print(number4)

            self.statementAnswered.text = question
            self.number1Label.setTitle(number1, for: .normal)
            self.number2Label.setTitle(number2, for: .normal)
            self.number3Label.setTitle(number3, for: .normal)
            self.number4Label.setTitle(number4, for: .normal)
        )
    , withCancel: nil)

这是 JSON 结构的 sn-p:

 "alert" : 
    "FjS4wUpXAUa5aWwXkjvujHxE4He2" : 
      "-La2uIRfXs15WP8bEfQo" : 
        "from" : "Gmg1ojNoBiedFPRNSL4sBZz2gSx2",
        "objectId" : "-La2uIRPzNXnamX4QLER",
        "timestamp" : 1552696293
      
    
  ,
  "questions" : 
    "Gmg1ojNoBiedFPRNSL4sBZz2gSx2" : 
      "-La2uIRPzNXnamX4QLER" : 
        "number 1" : "4444",
        "number 2" : "1111",
        "number 3" : "2222",
        "number 4" : "3333",
        "statement" : "favourite number",
        "selected" : "FjS4wUpXAUa5aWwXkjvujHxE4He2"
      
    
  ,

感谢任何帮助!

更新:

我已更新代码并在控制台上打印以下内容(应用上用户的 autoId):

[Snap (CjeP35ceAQZJuUPhm7U1eF3Yq4F3) 1, Snap 
(FjS4wUpXAUa5aWwXkjvujHxE4He2) 1, Snap (FoFQDAGGX9hntBiBdXYCBHd8yas2) 
1, Snap (PqMkClaPM3W8k7ZSgzAHb3yne5D3) 1]
[Snap (CjeP35ceAQZJuUPhm7U1eF3Yq4F3) 1, Snap 
(FjS4wUpXAUa5aWwXkjvujHxE4He2) 1, Snap (FoFQDAGGX9hntBiBdXYCBHd8yas2) 
1, Snap (PqMkClaPM3W8k7ZSgzAHb3yne5D3) 1]
[Snap (CjeP35ceAQZJuUPhm7U1eF3Yq4F3) 1, Snap 
(FjS4wUpXAUa5aWwXkjvujHxE4He2) 1, Snap (FoFQDAGGX9hntBiBdXYCBHd8yas2) 
1, Snap (PqMkClaPM3W8k7ZSgzAHb3yne5D3) 1]

(我会继续尝试让我的断点工作以查看问题所在并在此更新它是否有效)

提前致谢

更新:

我已经更改了数据库的结构,因此“问题”不会保存在 currentUser(回答问题的人)的 autoId 下,而只是创建的随机 Id,尽管我没有'认为这不是最有效的方法

【问题讨论】:

【参考方案1】:

问题1:

userRef.child(uniqueKey).observeSingleEvent(of: .value, with: snapshot )

没有必要再次观察用户参考,因为您已经从观察警报节点获得了所需的信息。

问题2:

让 questionNotification = self.ref.child("questions").child(senderDetails).child(self.userId)

在这一行中,您将用户 ID 引用到 self。查看您的 JSON 很明显,该字段将是动态的,因此在全球范围内将其删除是不明智的。

警告:

您需要处理命名约定。您分配的变量名称甚至不接近您收到的 JSON 响应。当您的项目变得更大时,如果您遇到任何错误,您将很难找到问题,因为您无法确定是哪个领域造成的。另外,请查看Codable 协议。它将使您对 JSON 对象的编码和解码工作更轻松。

解决方案:

guard let currentUser = Auth.auth().currentUser?.uid else  return 
    let ref = Database.database().reference()

    //enter alert node to get the new Id under the current user node
    let userRef = ref.child("alert").child(currentUser)
    userRef.observe(.childAdded, with:  (snapshot) in
        let uniqueKey = snapshot.key
        print(uniqueKey)
        guard let senderDetails = snapshot.childSnapshot(forPath: "from").value as? String else  return 
        guard let userID = snapshot.childSnapshot(forPath: "objectID").value as? String else  return 
        print(senderDetails)
        print(userID)

        let questionNotification = ref.child("questions").child(senderDetails).child(userID)
        questionNotification.observeSingleEvent(of: .value, with:  (snapshot) in
            let value = snapshot.value as? NSDictionary
            let statement = value?["statement"] as! String
            let number1 = value?["number 1"] as! String
            let number2 = value?["number 2"] as! String
            print(statement)
            print(number1)
            print(number2)
        )
    , withCancel: nil)

【讨论】:

感谢您的回复和解释!它似乎仍然无法正常工作,我试图让语句、number1 和 number2 在运行时显示在标签和 2 个按钮上,但它们仍然是空白的(我已经添加了代码更新) -获取 userId 时使用观察 .value 而不是 childAdded 事件会更好吗? 首先,我有两个问题: 1. 你能打印数据吗? 2.number1Label/number2LabelUIButton吗? 不,数据仍然没有打印,是的,它们是按钮,但我用 number1Label.isEnabled = false 和 number2Label.isEnabled = false 禁用了它们 :) 尝试在打印的每一行添加断点,让我知道哪一行没有执行。另外,如果您还没有,请照原样复制我的代码以进行测试,然后进行修改。确保currenUser 不为零。 我的断点似乎由于某种原因无法正常工作,但我注意到除了打印之外没有在任何地方调用 uniqueKey?另外,我现在已经复制了您的代码并且正在打印某些内容,但我不太确定如何链接它 - 我将更新我上面的代码以使其清晰

以上是关于输入一个子节点以获取进入另一个子节点所需的信息的主要内容,如果未能解决你的问题,请参考以下文章

如何反序列化xml文件的子节点

当另一个子div悬停时,更改子div的外观

使用fork()获取孩子的孩子

拖放一个子节点

替换节点(replaceChild())

删除节点(removeChild())