Swift - Unable to retrieving data from Firebase database - ios

I am a beginner Swift programmer. I am learning to retrieve data from Firebase database.
The debug console showed:
"Could not cast value of type '__NSDictionaryM' (0x11020b4f8) to 'NSString' (0x10f37b2a8).2018-03-26 15:49:25.442062+0800 messagingapp[4594:1197722] Could not cast value of type '__NSDictionaryM' (0x11020b4f8) to 'NSString' (0x10f37b2a8)".
I have put a breakpoint at the end of the code and managed to confirm that postDict correctly retrieve data from snapshot. However, the array postData just could not append. Would appreciate if anyone could give me advice to overcome this. Many thanks
var postData = ["message 1", "message 2"]
postRef = FIRDatabase.database().reference()
refHandle = postRef.observe(FIRDataEventType.value, with: { (snapshot) in
let postDict = snapshot.value as? [String : AnyObject] ?? [:]
// ...
for ( _, myvalue) in postDict {
self.postData.append(myvalue as! String)
}
self.tableView.reloadData()
})

Looking at your postDict debugging console output, I guess you simply forgot to access the "Posts" key (before filling the corresponding self.postData). For instance:
let valueDict = snapshot.value as? [String: AnyObject] ?? [:]
let postDict = valueDict["Posts"] as? [String: String] ?? [:]
// ...
for (_, postString) in postDict {
self.postData.append(postString)
}
By the way, you can further simplify your code by using the trailing closure syntax sugar as well:
refHandle = postRef.observe(FIRDataEventType.value) { (snapshot) in
/* observer body */
}

Related

How to resolve this: "Could not cast value of type 'NSTaggedPointerString' (0x105d25e88) to 'NSDictionary' (0x105d261a8)."

I am working with Firebase with the following structure:
When i click on saved button, this is the code that writes to firebase:
let savedDB = Database.database().reference().child("saved")
let postid = detailpost?.postid
let uid = Auth.auth().currentUser?.uid
let key = savedDB.child(postid!).key
let childUpdates : [String : String] = ["\(uid!)/\(key)/": "true"]
savedDB.updateChildValues(childUpdates)
To try to read the data, here's the code I have:
if let uid = Auth.auth().currentUser?.uid{
let savedDB = Database.database().reference().child("saved").child(uid)
savedDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String,String>
if let savedpostid = snapshotValue["postid"]{
......
When I the code gets to this step it crashes, with the following error message:
Could not cast value of type 'NSTaggedPointerString' (0x111688e88) to 'NSDictionary' (0x1116891a8).
I'm not able to figure out what causes this problem and how to resolve it. Can someone advice please? Thank you.
Change this:
let snapshotValue = snapshot.value as! Dictionary<String,String>
into this:
let snapshotValue = snapshot.value as! FIRDataSnapshot
check this link for more info: https://firebase.google.com/docs/reference/ios/firebasedatabase/api/reference/Classes/FIRDataSnapshot
A FIRDataSnapshot contains data from a Firebase Database location. Any time you read Firebase data, you receive the data as a FIRDataSnapshot.
I solved the issue myself by changing the code to as follows:
if let uid = Auth.auth().currentUser?.uid{
let savedDB = Database.database().reference().child("saved").child(uid)
savedDB.observe(.childAdded) { (snapshot) in
let savedpostid = snapshot.key
Thanks to folks for suggesting that the Dictionary is actually a String, which led me to the answer.

How to cast 'FIRDataSnapshot' to NSString & NSDict

I'm getting the error of could not cast value of type 'FIRDataSnapshot' to 'NSString'. Neither the retrieve names or retrieve quantities/manfacturers is working. Both give the same casting error essentially.
ref = Database.database().reference()
// Retrieve Names
ref.child("rawMaterials").observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
self.rawMaterialNames.append(child as! String)
}
})
//Retrieve Quantities and Manfacturers
for name in rawMaterialNames {
ref.child("rawMaterials/\(name)").observe(.value, with: { (snapshot) in
if let data = snapshot.value as? [String: Any] {
for i in data {
let quantity = data["quantity"] as! String
let manafacturer = data["manafacturer"] as! String
self.rawMaterialManafacturers.append(manafacturer)
self.rawMaterialQuantities.append(quantity)
//self.rawMaterialQuantities.append(data!["quantity"] as! String)
//self.rawMaterialManafacturers.append(data!["manafacturer"] as! String)
}
}
})
Edit: Since, no one has been able to help, maybe I'm not providing enough. My firebase realtime database tree looks like this
App Name
-contracts
---ContractTest
-rawMaterials
---Optional("Paint")
--------manafacturer: "Optional(\"Paint Company A\")"
--------quantity: "Optional(\"120\")"
---Optional("Lead")
You are missing a step to be able to cast to String:
ref.child("rawMaterials").observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let nameSnapshotValue = child.value as! FIRDataSnapshot
let name = nameSnapshotValue["name"] as! String //or whatever the dictionary key is...
self.rawMaterialNames.append(name)
}
})

Swift Get Specific Value From Firebase Database

I'm trying to get a specific value from Firebase Database. I looked some of the documents such as Google's, but I couldn't do it. Here is the JSON file of the database:
{
"Kullanıcı" : {
"ahmetozrahat25" : {
"E-Mail" : "ahmetozrahat25#gmail.com",
"Yetki" : "user"
},
"banuozrht" : {
"E-Mail" : "banuozrahat#gmail.com",
"Yetki" : "user"
}
}
}
Swift Code:
ref?.child("Kullanıcı").child(userName.text!).observeSingleEvent(of: .value, with: { (snapshot) in
if let item = snapshot.value as? String{
self.changedName = item
}
})
I want to get E-Mail value of a user, not everybody's. How can I do that?
At last I found a solution. If I declare a var and try to use later it returns nil, but if I try use snapshot.value as? String it's ok. Here is a example I did.
ref: FIRDatabaseReference?
handle: FIRDatabaseHandle?
let user = FIRAuth.auth()?.currentUser
ref = FIRDatabase.database().reference()
handle = ref?.child("Kullanıcı").child((user?.uid)!).child("Yetki").observe(.value, with: { (snapshot) in
if let value = snapshot.value as? String{
if snapshot.value as? String == "admin"{
self.items.append("Soru Gönder")
self.self.tblView.reloadData()
}
}
})
In your code, the snapshot will contain a dictionary of child values. To access them, cast the snapshot.value as a Dictionary and then accessing the individual children is a snap (shot, lol)
ref?.child("Kullanıcı").child(userName.text!)
.observeSingleEvent(of: .value, with: { (snapshot) in
let userDict = snapshot.value as! [String: Any]
let email = userDict["E-Mail"] as! String
let yetki = userDict["Yetki"] as! String
print("email: \(email) yetki: \(yetki)")
})
Add the "E-Mail" child to the query.
ref?.child("Kullanıcı").child(userName.text!).child("E-Mail").observeSingleEvent(of: .value, with: { (snapshot) in
if let item = snapshot.value as? String{
self.changedName = item
}
})

Firebase Accessing Snapshot Value Error in Swift 3

I recently upgraded to swift 3 and have been getting an error when trying to access certain things from a snapshot observe event value.
My code:
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
let username = snapshot.value!["fullName"] as! String
let homeAddress = snapshot.value!["homeAddress"] as! [Double]
let email = snapshot.value!["email"] as! String
}
The error is around the three variables stated above and states:
Type 'Any' has no subscript members
Any help would be much appreciated
I think that you probably need to cast your snapshot.value as a NSDictionary.
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let username = value?["fullName"] as? String ?? ""
let homeAddress = value?["homeAddress"] as? [Double] ?? []
let email = value?["email"] as? String ?? ""
}
You can take a look on firebase documentation: https://firebase.google.com/docs/database/ios/read-and-write
When Firebase returns data, snapshot.value is of type Any? so as you as the developer can choose to cast it to whatever data type you desire. This means that snapshot.value can be anything from a simple Int to even function types.
Since we know that Firebase Database uses a JSON-tree; pretty much key/value pairing, then you need to cast your snapshot.value to a dictionary as shown below.
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if let firebaseDic = snapshot.value as? [String: AnyObject] // unwrap it since its an optional
{
let username = firebaseDic["fullName"] as! String
let homeAddress = firebaseDic["homeAddress"] as! [Double]
let email = firebaseDic["email"] as! String
}
else
{
print("Error retrieving FrB data") // snapshot value is nil
}
}

Accessing Nested NSDictionary values in Swift 3.0

I have the following data I received from Firebase. I have made my snapshotValue a NSDictionary.
self.ref.child("users").child(facebookID_Firebase as! String).observeSingleEvent(of: .value, with: { (snapshot) in
let snapshotValue = snapshot.value as? NSDictionary
print(snapshotValue, "snapshotValue")
//this line of code doesn't work
//self.pictureURL = snapshot["picture"]["data"]["url"]
}) { (error) in
print(error.localizedDescription)
}
I tried How do I manipulate nested dictionaries in Swift, e.g. JSON data? , How to access deeply nested dictionaries in Swift , and other solutions yet no luck.
How do I access the url value inside the data key AND the picture key?
I can make another reference in Firebase and get the value, but I'm trying to save another request. 😓
When you refrence to a key of a Dictionary in swift you get out an unwrapped value. This means it can be nil. You can force unwrap the value or you can use pretty if let =
this should probably work.
if let pictureUrl = snapshot["picture"]["data"]["url"] {
self.pictureURL = pictureUrl
}
Try using :-
if let pictureDict = snapshot.value["picture"] as? [String:AnyObject]{
if let dataDict = pictureDict.value["data"] as? [String:AnyObject]{
self.pictureURL = dataDict.value["url"] as! String
}
}
Inline dictionary unwrapping:
let url = ((snapshot.value as? NSDictionary)?["picture"] as? NSDictionary)?["url"] as? String
You can use the following syntax, that is prettier:
if let pictureDict = snapshot.value["picture"] as? [String:AnyObject],
let dataDict = pictureDict.value["data"] as? [String:AnyObject] {
self.pictureURL = dataDict.value["url"] as! String
}
}

Resources