tim_d
tim_d

Reputation: 133

How can I access Firebase data under a childByAutoID?

I am currently trying to access some book data that was put into my database under a random child ID. I've been scouring other questions, but the farthest I've gotten is being able to access the ID within a closure. I can't figure out how to properly set up a completion handler to extract the ID.

Also, I don't know if there's a much easier way to be going about this?

Here's the data I'm trying to access: Firebase data

enter image description here

And here's my current code that needs a completion handler, I think?

func getChildID(department: String, course: String) {

        let parentRef = myDatabase.child("departments").child(department).child(course)

        parentRef.observeSingleEvent(of: .value) { (courseSnapshot) in
            if let data = courseSnapshot.value as? [String:String] {

                for value in data {
                    let isbn = value.value
                    if isbn != "ISBN" {

                        myDatabase.child("listings").child("\(isbn)").observeSingleEvent(of: .value, with: { (snapshot) in
                            let dictionary = snapshot.value as! NSDictionary
                            for key in dictionary.keyEnumerator() {
                                let myKey = key as! String
                                return
                            }
                        })
                    }
                }
            }
        }
    }

Upvotes: 2

Views: 245

Answers (2)

Jay
Jay

Reputation: 35667

Here we go. An answer to the question. However, and I mentioned in my comment to the question, the structure could be improved. However, there may be more children under each listing child so this answer handles it.

This just print's each authors name but it shows how to get to it so the answer should be expanded for the other child nodes.

let listingsRef = self.ref.child("listings")
listingsRef.observeSingleEvent(of: .value, with: { snapshot in
    for child in snapshot.children {
        let autoIdSnap = child as! DataSnapshot
        for autoChild in autoIdSnap.children {
            let childSnap = autoChild as! DataSnapshot
            let dict = childSnap.value as! [String: Any]
            let author = dict["author"] as! String
            print(author)
        }
    }
})

Oh, and a better structure may be

listings
   childByAutoId
      author: "Some author"
      listing: 9780184888
   childByAutoId
      author: "Another author"
      listing: 9799292598

Edit: If there will only ever be one and only one childByAutoId under each listing, you can eliminate the loop in the above and do this

let listingsRef = self.ref.child("listings")
listingsRef.observeSingleEvent(of: .value, with: { snapshot in
    for child in snapshot.children {
        let autoIdSnap = child as! DataSnapshot //each listing
        let childDict = autoIdSnap.value as! [String: Any] //a dict of items within the listing
        let firstKey = childDict.keys.first! //the key to the first item
        let valuesDict = childDict[firstKey] as! [String: Any] //the values for that key
        let author = valuesDict["author"] as! String //the author value
        print(author)
    }
})

Upvotes: 2

Arie Pinto
Arie Pinto

Reputation: 1292

You can observe changes in the last object before the childByAutoId(), in this case it would be "listings", and then create a model out of it.

override func viewDidLoad() {
    super.viewDidLoad()

    Auth.auth().signInAnonymously() { (user, error) in
        if error == nil{
            print("sign in successful")
        }
    }

    let query = myDatabase.child("listings")

    query?.removeAllObservers()

    query?.observe(.value, with: { snapshot in
        if snapshot.exists() {
            let booksSnapshot = Books(snap: snapshot)

            for children in booksSnapshot.books{
                let childByAutoId = children.value as! NSDictionary

                for books in childByAutoId{
                    let key = books.value as! NSDictionary

                    let book: Books = Books(fromJson: JSON())

                    book.author = key["author"] as! String
                    book.title = key["title"] as! String
                    book.price = key["price"] as! Int

                    print(book.price)
                }
            }
        }
    })
}

//Model //Note: you will have to install the 'SwiftyJSON' to create this model

import Foundation
import SwiftyJSON
import Firebase

class Books : NSObject{

var author : String!
var title : String!
var price : Int! // you can add more variables later
var books : [String: AnyObject]!

init(fromJson json: JSON!){
    if json.isEmpty{
        return
    }
    author = json["author"].stringValue
    title = json["title"].stringValue
    price = json["price"].intValue
}

/**
 * Instantiate the instance using the passed json values to set the properties values
 */
init(snap: DataSnapshot){
    let json = snap.value as! NSDictionary
    books = json as! [String: AnyObject]
}
}

Upvotes: 1

Related Questions