Get information from Firebase Database without autoID - swift

Currently, I'm getting information from my Firebase Database like the following:
Database.database().reference().child("users/BA917746-F5BE-4FA4-B23E-C998F4118CCE").observe(.childAdded) { (snapshot) in
let dict = snapshot.value as! [String: Any]
self.name = dict["name"] as! String
This is my JSON tree:
The information is being fetched where it's trying to unpack a random ID under the 'BA9...' part. How do I gather information from directly under the BA9 part with another autoID inside of it? Thank you.

I think the confusion stems from the fact that you are observing .childAdded. Since you're only observing one node/entity, you'll want to observe .value instead:
Database.database().reference()
.child("users/BA917746-F5BE-4FA4-B23E-C998F4118CCE")
.observe(.value) { (snapshot) in
let dict = snapshot.value as! [String: Any]
self.name = dict["name"] as! String
If you we're to observe the entire users node, that's when you'd either use .childAdded or loop over the child nodes of the snapshot.

Related

Anyone know how to resolve "Ambiguous use of 'subscript(_:)'" error with Firebase?

I am trying to develop followers for an app. Here is the code I have to retrieve the current authenticated users (minus the logged in user) and create a local list. I also have code to write a followers list to the Firebase but just this code (step 1) is throwing errors.
func retrieveUsers() {
let ref = Database.database().reference()
ref.child("users").queryOrderedByKey().observeSingleEvent(of: .value, with: {snapshot in
let users = snapshot.value as! [String: AnyObject]
self.user.removeAll()
for (_, value) in users {
if let uid = value["uid"] as! String {
if uid != Auth.auth().currentuser.uid {
let userToShow = User()
if let firest_name = value["firest_name"] as? String {
userToShow.userId = uid
self.user.append(userToShow)
}
}
}
}
self.tableView.reloadData()
})
}
if let uid = value["uid"] as! String {
is throwing Ambiguous use of 'subscript(_:)' which I really do not understand. Any help is appreciated!
You're casting your users constant to type [String: AnyObject]. In the loop where you're iterating the dictionary you try to create a constant uid assuming that value is a dictionary with String keys. However you don't know that since it is AnyObject as per your previous cast. AnyObject doesn't respond to subscript(_:) hence your error.
If you know that snapshot.value is indeed a [String: Dictionary] then you can change your cast type or you could cast value to this type.
Also note that using a force cast is a bad practice and can lead to nasty and hard to find bugs.

Adding Firestore to my project give an error to my Realtime Database Queries

I've been using Firebase Real-time Database in my project for quite some time now. Recently I added the pod for Firestore to use it together with the other database and all my queries and only the queries for Real-time Database are getting the following error: "Ambiguous use of 'subscript'".
If I uninstall the pod everything comes back to normal with absolutely no errors.
This is how I was using the code before: (working)
func retriveObjects() {
ref.child("Dinner").queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in
let allPosts = snapshot.value as! [String : AnyObject]
for (_, item) in allPosts {
if let itemCount = item["itemCount"] as? String {
print(itemCount)
}
}
}
}
Now this line is giving me the error:
if let itemCount = item["itemCount"] as? String
What can I do to make it work again but keeping both databases?
As mentioned in the comments, the value of the snapshot is being cast as a Dictionary of [String: AnyObject] and then you're trying to use item as a Dictionary but it's cast to AnyObject (which is not a dictionary). In other words item["itemCount"] doesn't work for AnyObject.
It's unclear what is throwing that error but we have a number of projects with both and it's not throwing that error. You may want to consider changing the code up a bit;
self.ref.child("Dinner").queryOrderedByKey().observeSingleEvent(of: .value) { (snapshot) in
let allPosts = snapshot.children.allObjects as! [DataSnapshot]
for post in allPosts {
let itemCount = post.childSnapshot(forPath: "itemCount").value as? String ?? "No Count"
print(itemCount)
}
}

Pull string value from firebase snapshot

I am a new Swift developer. I'm using Swift 4.2 and Xcode 10.1.
I'm trying to create an array of strings from a firebase snapshot. I am able to do this by setting up a struct model and using an initializer, but when I want to do it directly in the code without a separate struct it does not work. Here is my code:
// Get the likers
dbRef.child("likers").observeSingleEvent(of: .value) { snapshot in
// Declare an array to hold the Likers
var retrievedLikers = [String]()
// Loop through the retrieved likers and put into the array
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String:Any]
let likerId = dict["userId"] as? String ?? ""
print (likerId)
retrievedLikers.insert(likerId, at: 0)
}
likers = retrievedLikers
}
My firebase data model looks like this:
I have tried several methods. The code above is the most recent based on another SO suggestion.
The problem is that I can't create a dictionary with snap.value. Snap has the correct data. I am getting an error saying "Could not case value of type '__NSCFString' to 'NSDictionary'. But the snap is showing as a dictionary. Here's a screenshot:
Any help would be appreciated. I've tried for 3 hours to solve this.
You can try
let res = snapshot.value as! [String:String]
retrievedLikers = Array(res.values)
Here the crash snap.value is a String that can't be casted to [String:Any]
let dict = snap.value as! [String:Any]

Firebase Add New Key/Value to Pre-existing database without crashing xcode

` let query = ref?.child("Reviews").queryOrdered(byChild: "UserID").queryEqual(toValue: myUser.userId)
query?.observeSingleEvent(of: .value) { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let uid = dict["UserID"] as! String
let review = dict["Body"] as! String
let rating = dict["Rating"] as! String
let titleID = dict["TitleID"] as! String
let reviewID = dict["ReviewID"] as! String
let ratingID = dict["RatingID"] as! String
`
THE ERROR OCCURS AT THE ratingID call to the database. It unwraps nil.
I am trying to adapt a pre existing Firebase database with a new key/value.
I then try to display entries in my tableview and I get a crash with unwrap returning nil. I know why this is happening and it's because the previous data does not have the new key/value I want to include in the node going forward. I have tried many different things such as if let and guard let without much fortune. How do I add new key/Values and still have the tableview read entries that don't have the new value?
I include an image of the current node and I want to add a 'RatingsID' to the node. When I do, I get the unwrap nil error.
Database node prior to new key/value
Your code is super close, just need to protect the code in case the ratingID key doesn't exist.
So change
let ratingID = dict["RatingID"] as! String
to
let ratingID = dict["RatingID"] as! String ?? ""
So if the RatingID node does not exist, you'll set ratingID to an empty string (or whatever string you want)
You could also code it to only operate on the value of that key if the node exists (not nil)
if let someVal = dict["xxx"] {
//do something with someVal
} else {
print("xxx node wasn't found")
}
Here's a complete example: We are reading some messages from the messages node and some of them have a test_key node and some dont. For those that don't, default string is assigned to test
let postsRef = self.ref.child("messages")
postsRef.observe(.childAdded) { snapshot in
let dict = snapshot.value as! [String: Any]
let msg = dict["msg"] as! String
let test = dict["test_key"] ?? "default string"
print(msg, test)
}

firebase snapshot key for children autoids

I have the following structure :
DATA :
-kojasd- <----- child by autoid key name for folder
property:value
-kjofs- <----- child by aytoid key name for folder
property:value
how can I get the key value of the childbyautoid() in a snapshot.children loop ?
here s a bit of code to explain :
for items in snap.children {
let key = items.key as! String // DOESN T WORK
let value = items.value!!["property"] as! String
}
in this code, snap refers to DATA
I thought that it would be easy to get this key value, but I m stucked here since a long time, any help ?? :)
sincerely
Yann
For people who are using new Xcode 8 beta 3 and swift 3 , many notations have changed and something like the snippet below should give you the children values as String ; basically you would need to do another check and safely upward:
for childSnap in snapshot.children.allObjects {
let snap = childSnap as! FIRDataSnapshot
if let snapshotValue = snapshot.value as? NSDictionary, let snapVal = snapshotValue[snap.key] as? AnyObject {
print("val" , snapVal)
}
}
If let's say you have posts you can get it like this.
ref.child("posts").observeEventType(FIRDataEventType.Value, withBlock: { snapshot in
for childSnap in snapshot.children.allObjects {
let snap = childSnap as! FIRDataSnapshot
print(snap.key)
let property = snap.value!["property"] as! NSString
}
})
I know the awnser was already given but I wanted to give some more explanation.
I have spent a few moments with that too and although you said this doesn't work for you, I think this is how it should be done:
rootRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
for item in snapshot.children {
print(item.key)
}
})
ok, found a solution, I had to pass the snap into a new fdatasnapshot to get its key