Firebase snapshot returns null - ios

Hi guys I have been using firebase to write and read values from the database. It was working awesome until I wrote a function to retrieve values or products stored using swift in the following way.
Here is my code
func retrieveLiveUrlFor(product: Product){
if let path = product.prodRef{
print("Looking for : \(path)")
var liveUrl = ""
let ref = Database.database().reference(withPath: path)
ref.observe(. value, with: {
snapshot in
print("Snap : \(snapshot.value)")
if snapshot.exists(){
print("Snap : \(snapshot.value)")
let dic = snapshot.value as? NSDictionary
if dic != nil{
let url = dic?["liveUrl"] as? String
print("Url is here")
if url != nil{
print("URL is not nil")
liveUrl = url as! String
}
}
}
if (self.productdelegate != nil){
print("Calling Product delegate")
self.productdelegate?.liveUrlObtained!(liveUrl: liveUrl)
}
})
}
}
And this is the value of the path that I am trying to retrieve
Products/Live/Global/WpMvDJZUclRlfHFJsSlBEbi0jHf1
And here is the snap of the firebase database
The snapshot.value alwasy returns null in swift.
When I print using
print("Snap: \(snapshot.value)")
It prints the following
Snap : Optional()
Please guide me what I am doing wrong so that I can get to it.

If you are observing using the .value event, then a return of snapshot.value as nil means that the snapshot value does not exist at that reference. Try printing the snapshot as a whole and the snapshot.key
ideally the reference you need is
let ref = Database.database.reference().child("Products").child("Live").child("Global").child("WpMvDJZUclRlfHFJsSlBEbi0jHf1")
The observer would function like this:
ref.observe(.value) {(snapshot) in
print(snapshot.value!)
}

Related

Retrieve last child from child node firebase realtime database swift 4

This is my firebase realtime database
Image link
This is the snippet i am using its always returning nil
let rootRef = Database.database().reference()
rootRef.child("POSTS").queryLimited(toLast: 1).observeSingleEvent(of: .value) { (myDataSnap) in
let value = myDataSnap.value as? NSDictionary
print(value as? Any)
}
If you are trying to access Id and Id's can be anything other than 0.
Than you can try the snippet below
let Key = rootRef.child("POSTS").childByAutoId().key
rootRef.child("POSTS").child(Key!).setValue(postData.toDictionary()){
(error:Error?, ref:DatabaseReference) in
if let error = error {
print("Data could not be saved: \(error).")
} else {
//do stuff
}
}
Use .childAdded or childChanged instead of .value, this might solve it
let rootRef = Database.database().reference()
rootRef.child("POSTS").queryLimited(toLast: 1).observeSingleEvent(of: .childChanged) { (myDataSnap) in
let value = myDataSnap.value as? NSDictionary
print(value as? Any)
}

How to get values inside nested keys in Firebase on Swift

I'm trying to get values inside two nested keys in Firebase.
:
I need to put all the value of name inside an array. Here is my code where I'm accessing just the node "user". I was thinking that I could use "queryOrderedByKey" one after another, but in that case xCode crashes and says something like multiple quires aren't allowed.
Database.database().reference().child("user").queryOrderedByKey().observe(.childAdded) { (snapshot) in
if snapshot.value != nil {
let result = snapshot.value as! [String : AnyObject]
if let name = result["name"] as? String {
self.myArray.append(name)
}
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}
And this is what I'm getting when printing the result.
Here is the answer
Database.database().reference().child("user").observe(.childAdded) { (snapshot) in
if let dictinoary = snapshot.value as? [String: Any] {
if let myFinalStep = dictinoary["GeneralInformation"] as? [String: Any] {
print(myFinalStep["name"])
}
}
}
Tigran's answer is very good but here's an alternative. This code iterates over each child node within 'user' node and looks into a deep path to get the name. Note this leaves a childAdded observer to the user node so if any additional nodes are added, this will fire again.
let usersRef = self.ref.child("user")
usersRef.observe(.childAdded, with: { snapshot in
if let name = snapshot.childSnapshot(forPath: "GeneralInformation")
.childSnapshot(forPath: "name").value as? String {
print(name)
}
})
If you want to read the names in once and not leave an observer, here's an alternative
let usersRef = self.ref.child("user")
usersRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
if let name = snap.childSnapshot(forPath: "GeneralInformation")
.childSnapshot(forPath: "name").value as? String {
print(name)
}
}
})
I was feeling Swifty so here's a third variant if you don't want to leave an observer. Note that if the node containing the name does not exist, the resulting array will contain "No Name" at that index.
let usersRef = self.ref.child("uses")
usersRef.observeSingleEvent(of: .value, with: { snapshot in
let myUsers = snapshot.children.allObjects.map { $0 as! DataSnapshot }
let names = myUsers.map { $0.childSnapshot(forPath: "GeneralInformation")
.childSnapshot(forPath: "name")
.value as? String ?? "No Name" }
print(names)
})

How to retrieve data from current User in Firebase using Swift?

I am trying to get current users firstname from firebase using swift code. Below is my JSON file and swift code. But it's not retrieving first name. Please suggest
Json:
Swift code:
if FIRAuth.auth()?.currentUser != nil{
let queryRef = FIRDatabase.database().reference().child("expatsappmembers")
let userID : String = (FIRAuth.auth()?.currentUser?.uid)!
print("Current user ID is" + userID)
queryRef.child("uid").child(userID).observeSingleEvent(of: .value, with: {(snapshot) in
print(snapshot.value)
let userName = (snapshot.value as! NSDictionary)["firstname"] as! String
print(userName)
})
}
It is slightly different to get a value from Firebase in Swift 3
the proper way to do it is:
ref.child("expatsappmembers").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let firstName = value?["firstname"] as? String
// ...
}) { (error) in
print(error.localizedDescription)
}

Iterate through all keys of one child in Firebase

This is my structure in the Firebase Realtime database:
I want to get for all products the name.
Here's what I tried:
database.child("customerID").child("productTopSeller").observe(FIRDataEventType.value, with: { (snapshot) in
for childSnap in snapshot.children.allObjects {
let product = childSnap as! FIRDataSnapshot
print(product.value?["name"] as? String ?? "")
}
}) { (error) in
print(error.localizedDescription)
}
But this gives my following error:
Type 'Any' has no subscript members.
I know I would need to cast the snapshot somehow but couldn't figure out how to do this. using Swift 3.
You need to cast product.value to [String:Any]. Look ad the following code
ref.child("customerID").child("productTopSeller").observeSingleEvent(of: .value, with: { snapshot in
let names = snapshot
.children
.flatMap { $0 as? FIRDataSnapshot }
.flatMap { $0.value as? [String:Any] }
.flatMap { $0["name"] as? String }
print(names)
})
Please note I am using observeSingleEvent in order to get only one callback from Firebase.
Your code does use observe instead which produce a callback every time the observed data does change.

Retrieving and Reading Data as NSArray from Firebase (Swift 3)

I'm working through a course on Udemy to build a chat app with Firebase, Backendless, and Swift. All of the issues (it was written for Swift 2 not 3) I've been able to resolve myself, but this one has me stumped. This function is supposed to retrieve data from the Firebase database, and apparently it was supposed to retrieve it as an NSArray, but it now retrieves it as an NSDictionary, which is making a huge list of errors in the other functions because it's not expecting a dictionary.
func loadRecents() {
firebase.childByAppendingPath("Recent").queryOrderedByChild("userId").queryEqualToValue(currentUser.objectId).observeEventType(.Value, withBlock: {
snapshot in
self.recents.removeAll()
if snapshot.exists() {
let sorted = (snapshot.value.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptior(key: "date", ascending: false)])
}
})
}
I've updated to Swift 3 as far as:
func loadRecents() {
ref = FIRDatabase.database().reference()
let userId = currentUser?.getProperty("username") as! String
ref.child("Recent").queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: {
snapshot in
self.recents.removeAll()
if snapshot.exists() {
let values = snapshot.value as! NSDictionary
}
})
}
Of course, using as! NSArray does not work. Would very much appreciate it if anyone can suggest a method to update this to use Swift 3, sort it by a value in the data, and be able to access it later on. Thanks!
func loadRecents() {
ref = FIRDatabase.database().reference()
let userId = currentUser?.getProperty("username") as! String
ref.child("Recent").queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: {
snapshot in
self.recents.removeAll()
if snapshot.exists() {
let values = snapshot.value as! [String:AnyObject]
}
})}
or you can use also let values = snapshot.value as! [Any]
Hope this will help you, try this code:
func loadRecents() {
let ref = FIRDatabase.database().reference()
let userId = currentUser?.getProperty("username") as! String
ref.child("Recent").queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: {
snapshot in
self.recents.removeAll()
guard let mySnapshot = snapshot.children.allObjects as? [FIRDataSnapshot] else { return }
for snap in mySnapshot {
if let userDictionary = snap.value as? [String: Any] {
print("This is userKey \(snap.key)")
print("This is userDictionary \(userDictionary)")
}
}
})
}

Resources