3

How to loop through Firebase data (childs) which are actually objects and access to their properties in Swift 4?

As a beginner with Swift, I am trying to loop through data I am retrieving from Firebase, and I am trying to access to properties of those objects. Seems much more complicated then it should be in swift (just my subjective opinion)

As per documentation on the Firebase site this is what I have

_commentsRef.observe(.value) { snapshot in
    for child in snapshot.children {
        // Access to childs here ...
    }
}

Now, combining this above and as per tutorials and explanations (btw was not able to find neither one which explains this fully) which I found on net, this is what I have:

ref.child("activities").child("list").observeSingleEvent(of: .value, with: { (snapshot) in
    // The list i got here is the list of the childs which are objects
    // Lets loop through that list and pull properties we need
    for child in snapshot.children.allObjects as! [DataSnapshot] {
        print(child.value)
    }
})

The print in the loop will properly display object with all of its properties, but I am not able to access to these properties. Accessing to it with something like "child.value.title" is resulting with error "Value of type 'Any' has no member 'title'"

Do I need to convert child.value to something else, maybe to cast it or to convert it somehow to property accessible JSON or something like that?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
cool
  • 3,225
  • 3
  • 33
  • 58

1 Answers1

5

If you call value on a snapshot that contains multiple properties, what you get back is a NSDictionary with the property names as the keys. So to get the value of the title key you'd do:

for child in snapshot.children.allObjects as! [DataSnapshot] {
    print(child.value)
    let dict = child.value as? [String : AnyObject] ?? [:]
    print(dict["title"])
}

Alternatively you can use the other members of DataSnapshot to navigate to the title property and then call .value on that:

for child in snapshot.children.allObjects as! [DataSnapshot] {
    print(child.value)
    print(child.childSnapshot(forPath: "title").value)
}

See DataSnapshot.value and the first sample in the Firebase documentation on reading data.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • First solution works fine with "let dict = child.value as? [String : AnyObject] ?? [:]." and not with the snapshot it seems. The second solution in my case says: "Value of type 'DataSnapshot' has no member 'child' – cool Mar 19 '18 at 02:24
  • Oops, I keep forgetting it's `childSnapshot(forPath:)` in Swift. See https://firebase.google.com/docs/reference/swift/firebasedatabase/api/reference/Classes/DataSnapshot#childsnapshotforpath. Sorry about that. – Frank van Puffelen Mar 19 '18 at 03:48
  • Indeed it is workig now... Just one more change, it seems that DataSnapshot is not optional anymore, hence using question mark for the second solution failing. Without it works fine. – cool Mar 19 '18 at 12:22
  • 1
    Thanks for pointing that last mistake out. I updated the code in the answer. – Frank van Puffelen Mar 19 '18 at 14:17