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]
Related
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.
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)
}
}
` 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)
}
So I am currently working on a personal project to help understand API's and how they work..so I am still a little new to iOS Development. I have already connected to the URL and gotten the data however now I am trying to make the results a little bit more clear cut.
Below is the code for the class (when the button is clicked it prints all this information)
First part of code
Second part of code
The error I get is Type 'Any' has no subscript members. Any idea as to why? Or how this can be fixed?
you can set their types like this then you can print values.
if let main = json["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
let temp_max = main["temp_max"] as? Double
print("temp\(temp_max!)")
let temp_min = main["temp_min"] as? Double
print("temp\(temp_min!)")
}
let items = json["weather"] as! [AnyObject]
let main = items[0]["main"] as! String
print(main)
let description = items[0]["description"] as! String
print(description)
let icon = items[0]["icon"] as! String
print(icon)
let name = json["name"] as! String
print("name\(name)")
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