如何使用 Swift 使用 Firebase 正确观察两个连接节点

Posted

技术标签:

【中文标题】如何使用 Swift 使用 Firebase 正确观察两个连接节点【英文标题】:How to properly observe two joined nodes with Firebase using Swift 【发布时间】:2017-05-28 18:34:12 【问题描述】:

此问题源于此:Join different nodes to observe them at once with firebase。如果它非常相似,我深表歉意,但我正在努力在我的项目中解决它。

我有一个IngredientData,它获得了几种成分和一个属性:


  "IngredientData": 
    "-KkY92MUZNHXxg4ivGY7": 
      "name": "Onions"
    ,
    "-KkY90e7dAgefc8zH3_F": 
      "name": "Peas"
    ,
    "-KkY9-HWJANdfhmD-SJ-": 
      "name": "Mushrooms"
    ,
    "-KkbWdomTYdpgEDLjC9w": 
      "name": "Eggs"
    ,
    "-KkbXOECSCBNAcVaO9rp": 
      "name": "Rice"
    
  

然后我有一个 RecipeData,其中包含 recipe 并且里面是 ingredients


  "RecipeData": 
    "-KlApwz5Y-TK_9z1sV1i": 
      "recipeName": "Fried Rice",
      "ingredients": 
        "-KkbWdomTYdpgEDLjC9w": true,
        "-KkbXOECSCBNAcVaO9rp": true,
        "-KkY90e7dAgefc8zH3_F": true
      
    
  

我现在正在尝试获取配方中成分的详细信息,以便获取 name 属性。我有一个在配方成分中迭代的函数:

func fetchRecipeIngredients() 

    let databaseRef = FIRDatabase.database().reference().child("RecipeData/recipe/-KlApwz5Y-TK_9z1sV1i/ingredients")

    databaseRef.observeSingleEvent(of: FIRDataEventType.value, with:  snapshot in
        for ingredients in snapshot.children 

            print(snapshot)
        
    )

这是我的Recipe 课程:

class Recipe 

    var name: String!
    var key: String

    init(from snapshot: FIRDataSnapshot) 

        let snapshotValue = snapshot.value as! [String: Any]

        self.name = snapshotValue["recipeName"] as! String
        self.key = snapshot.key
    

我有两个主要问题:

    首先,目前我不确定如何迭代特定配方,或者这对于我想要实现的目标是否必要。现在我已经对 recipeID 进行了硬编码,以便能够在其中进行迭代。

    使用这个fetchRecipeIngredients()时如何获取成分详情@

提前谢谢:)

【问题讨论】:

【参考方案1】:

给你。

从 Firebase 结构开始


  "IngredientData" : 
    "ingredient_0" : 
      "name" : "Onions"
    ,
    "ingredient_1" : 
      "name" : "Peas"
    ,
    "ingredient_2" : 
      "name" : "Mushrooms"
    ,
    "ingredient_3" : 
      "name" : "Tomatoes"
    ,
    "ingredient_4" : 
      "name" : "Dough"
    
  ,
  "RecipeData" : 
    "recipe_0" : 
      "ingredients" : 
        "ingredient_0" : true,
        "ingredient_1" : true,
        "ingredient_2" : true
      ,
      "name" : "Fried Rice"
    ,
    "recipe_1" : 
      "ingredients" : 
        "ingredient_0" : true,
        "ingredient_2" : true,
        "ingredient_3" : true,
        "ingredient_4" : true
      ,
      "name" : "Pizza"
    
  

跟你的差不多

我们有一个加载特定配方的主函数,然后是加载成分的函数。

   func loadRecipe() 
        let recipiesRef = self.ref.child("RecipeData")
        let recipieToLoadRef = recipiesRef.child("recipe_1")

        recipieToLoadRef.observeSingleEvent(of: .value, with:  snapshot in
            let recipieDict = snapshot.value as! [String:Any]
            let name = recipieDict["name"] as! String
            let ingredientsSnap = snapshot.childSnapshot(forPath: "ingredients")
            print(name)
            self.loadIngredients(ingredientSnap: ingredientsSnap)
        )
    

    func loadIngredients(ingredientSnap: DataSnapshot) 
        let ingredientsRef = self.ref.child("IngredientData")

        for ingredient in ingredientSnap.children 
            let snap = ingredient as! DataSnapshot
            let ingredientKey = snap.key
            let thisIngredient = ingredientsRef.child(ingredientKey)
            thisIngredient.observeSingleEvent(of: .value, with:  snapshot in
                let ingredientDict = snapshot.value as! [String: Any]
                let ingredientName = ingredientDict["name"] as! String
                print("  \(ingredientName)")
            )
        
    

和输出

Pizza
  Onions
  Mushrooms
  Tomatoes
  Dough

编辑

回应后续评论:

如果您的用户想要存储他们的收藏夹,则创建一个节点

favorites
   recipe_1: true
   recipe_2: true

通过 .value 观察 /favorites 节点(这将一次读取他们所有的收藏夹。迭代快照中的子节点。键将是配方节点名称(recipe_1 和 recipe_2)。然后您可以加载每个直接来自节点的配方名称 (/recipe_1/name) 并填充一个数组,您可以将其用作 tableView 的数据源

【讨论】:

非常感谢您的回答,它运行良好。只有一个关于确定特定配方的问题。目前,我不得不在recipieToLoadRef 中硬编码该ID,以获取配方成分 的详细信息。但是,假设我想为用户创建一个favouriteList 以添加配方,我将如何指定要进入哪个配方然后显示在 tableView 之类的东西上?我已经尝试使用您为此所做的相同方法。如果这个问题无关紧要,请不要担心。再次感谢:) @Chace 很高兴它有帮助!我用一些额外的信息更新了答案,以解决您的后续问题。 我很欣赏这个答案。我已经尝试过了,我能够打印出用户收藏夹中的食谱。但是,您可以直接从节点加载每个配方名称 (/recipe_1/name) 并填充可以用作 tableView 数据源的数组 的部分是我卡在的地方:/ @Chace 这里有很多关于堆栈溢出的示例,展示了如何从 Firebase 读取数据并填充数据源。我建议搜索这些,然后尝试一些代码。如果您遇到困难,请发布问题! (确保它不是重复的!) @Chace 我的答案中的代码两者兼而有之;它获取配方并打印名称,然后获取成分并打印它们。如果您查看答案的底部,我会包含代码的输出;比萨是名字,成分是洋葱、蘑菇、西红柿和面团。

以上是关于如何使用 Swift 使用 Firebase 正确观察两个连接节点的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 中的 url 从 firebase 正确检索数据?

使用 Swift 3 调试 Firebase

新的 Firebase 数据导致 TableView 单元格闪烁 (Firebase/iOS/Swift)

Swift - 我如何检查 firebase 服务器是不是可用?

使用 swift 将数据写入 Firebase

使用 Firebase 和 Swift (iOS) 上传图片