Dia
Dia

Reputation: 237

Accessing Nested Children in Firebase Database Swift 3

My current firebase database structure is like this

customer
  -L1x2AKUL_KNTKXyza
    name:"abc"
    subscription
      -L1x2AKlvmG0RXv4gL
        sub_no: "123"
        sub_name: ""
      -L1x2AKlvmG0RXv4ab
        sub_no: "456"
        sub_name" ""
  -L1x2AKUL_KNTKXymk
    name:"xyz"
    subscription
      -L1x2AKlvmG0RXv4xy
        sub_no: "789"
        sub_name: ""

I am trying to access all subcriptions of all customer records at once.

This is the code I am using:

var ref: DatabaseReference!

ref = Database.database().reference(withPath: "customer")

ref.observe(.value, with: { snapshot in
        let enumerator = snapshot.children

        while let rest = enumerator.nextObject() as? DataSnapshot {

            let imageSnap = rest.childSnapshot(forPath: "subscription")
            let dict = imageSnap.value as! NSDictionary

            //self.vehicleListDict.append(dict.object(forKey: "sub_no") as! NSDictionary)

            print("value : \(dict)")

        }
        print("vehicleListDict : \(self.vehicleListDict)")
    }) { (error) in
        print(error.localizedDescription)
    }

I am unable to access all the subscriptions within all customer records at once. Its only accessing till one level. I tried to put a while loop within the while that exists but that also does not give me the output needed. It goes in an infinite loop instead. Please could anyone help. I am using firebase realtime database for the first time.

The fetched values should be

123
456
789

Upvotes: 1

Views: 1267

Answers (1)

Jay
Jay

Reputation: 35648

The code for doing specifically what you are asking is

let customerRef = self.ref.child("customer")
customerRef.observe(.childAdded, with: { snapshot in
    let subscriptionSnap = snapshot.childSnapshot(forPath: "subscription")
    for child in subscriptionSnap.children {
        let snap = child as! DataSnapshot
        let dict = snap.value as! [String: Any]
        let subNo = dict["sub_no"] as! String
        print(subNo)
    }
})

and the output is

a123
a456
a789

*note that I am reading the sub_no as a STRING which is why I added 'a' in front. If they are actually integers change the line to

let subNo = dict["sub_no"] as! Integer

*note2 this will leave a .childAdded observer to the main node in question so any further children that are added will fire the code in the closure.

Edit:

If you want to just retrieve all of the data at one time and not leave a childAdded observer then this will do it:

let customerRef = self.ref.child("customer")
customerRef.observeSingleEvent(of: .value, with: { snapshot in
    for customerChild in snapshot.children {
        let childSnap = customerChild as! DataSnapshot
        let subscriptionSnap = childSnap.childSnapshot(forPath: "subscription")
        for subscriptionChild in subscriptionSnap.children {
            let snap = subscriptionChild as! DataSnapshot
            let dict = snap.value as! [String: Any]
            let subNo = dict["sub_no"] as! String
            print(subNo)
        }   
    }
})

and the output is

a123
a456
a789

Upvotes: 4

Related Questions