1

Here is my data structure:

{ "ItemData": {
    "Item": [
      {
        "name": "Table",
        "measurement ": [
          {
            "height": 30
          },
          {
            "width": 50
          }
        ]
      }
    ]
  }
}

I can currently fetch all the data from Firebase and able to display the name on to a tableView. I am now trying to get the values that are nested inside the 'measurement' i.e. 'height' & 'width'. I have looked at Query Firebase for nested child swift, What's the best way of structuring data on firebase?, Iterate through nested snapshot children in Firebase using Swift and Firebase Swift 3 Xcode 8 - iterate through observe results but still have no clue how to solve this.

This is my Item class:

class Item {

    var name: String!
    var measurement: String!
    var key: String

    init(from snapshot: FIRDataSnapshot) {

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

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

    }
}

This is the function I use to fetch the item. The ItemManager is a class that has the function to remove and add the array of Item:

func fetchItem() {

    let databaseRef = FIRDatabase.database().reference(withPath: "ItemData/Item/")

    databaseRef.observe(.value, with: { snapshot in

        ItemManager.shared.removeAll()
        for item in snapshot.children {
            guard let snapshot = item as? FIRDataSnapshot else { continue }


            let item = Item(from: snapshot)
            ItemManager.shared.additem(item)
            print(snapshot)
        }

        self.tableView.reloadData()
    })

}

Please help me if you can :)

Community
  • 1
  • 1
Chace
  • 561
  • 10
  • 28
  • Which error are you getting? – Pedro Castilho Apr 27 '17 at 16:19
  • Your first problem is that `measurement` is an array, so all its elements should be of the same type. However, you use the first element for `height` and the next for `width`. If you have control over this, change measurement to be a dictionary. That way, it'll be easy to retrieve `width` and `height`. – paulvs Apr 27 '17 at 16:19
  • @PedroCastilho I am not getting any error. I am just trying to get the values inside measurement. – Chace Apr 27 '17 at 16:25
  • @paulvs Thanks for this advice and I get what you mean, however I'm not sure how to implement this change. Do I just make the measurement be an NSDictionary? – Chace Apr 27 '17 at 16:25

1 Answers1

4

As suggested in comment measurement array of dictionary not the String, So if you want to get height and width from it you can get it this way.

class Item {

    var name: String!
    var heightMeasurement: String!
    var widthMeasurement: String!
    var key: String

    init(from snapshot: FIRDataSnapshot) {

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

        self.name = snapshotValue!["name"] as! String
        if let array = snapshotValue["measurement"] as? [[String:Any]], 
           let heightDic = array.first, let height = heightDic["height"],
           let widthDic = array.last, let width = widthDic["width"] {            

             self.heightMeasurement = "\(height)"
             self.widthMeasurement = "\(width)"
             print(height, width)
        }
        else {
             self.heightMeasurement = "" //set some default value
             self.widthMeasurement = ""  //set some default value
        }
        self.key = snapshot.key     
    }
}

Note: If your array having more than two objects than to get the height and width you need to subscripting the array index first to get the dictionary and then access its key according to get your value.

Nirav D
  • 71,513
  • 12
  • 161
  • 183
  • Thank you for this Nirav but it hasn't seemed solved my issue. Nothing gets printed from the code you have provided. – Chace Apr 27 '17 at 17:04
  • @Chace Try once replacing `[[String:Int]]` with `[[String:Any]]` – Nirav D Apr 27 '17 at 17:05
  • Ok, it works and prints out the values. But how do I call this on lets say a UIlabel. I've tried cell.heightLbl.text = item.measurement but nothing happens and pretty sure is incorrect. – Chace Apr 27 '17 at 17:21
  • Sorry, I'll make it more clear I want the separate labels to display how many values measurement has (in this case 2). And display these values, so height = "30" and width = "50". – Chace Apr 27 '17 at 17:38
  • @Chace Check the edited answer and now you can set it like `cell.heightLbl.text = item.heightMeasurement` same goes for width – Nirav D Apr 27 '17 at 17:52
  • @Chace Greats :) Glad it works for you also I edited `[[String:Int]]` to `[[String:Any]]` – Nirav D Apr 27 '17 at 18:08