Could not cast value of type '__NSCFString' to 'NSDictionary' switft 5 - swift

I want to get list of users from Firebase database and put that in a Users array but I am unable to get data from the snapshot
This is what I have tried
class User: NSObject {
var name: String?
var email: String?
}
var users : [User] = []
func fetchUsers() {
Database.database().reference().child("users").observe(.childAdded) { (snapshot) in
for child in (snapshot.children) {
let snap = child as! DataSnapshot
let dic = snap.value as! [String: String] // erros here
//print((dic["name"]))
//WANT TO LOAD THE LIST OF USERS INTO `var users`
}
}
}
Error
Could not cast value of type '__NSCFString' to 'NSDictionary'
This is how my data looks like on firebase database
Thanks for your help
R

That's because DataSnapshot is a String to Object dictionary. This should do the trick
guard let dict = child.value as? [String : AnyObject]
else {
print("couldn't cast to dictionary")
return
}
print("successfully cast to dictionary")
print(dict["name"])
print(dict["email"])

func fetchUsers() {
Database.database().reference().child("users").observe(.childAdded) { (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
print(child.value)
if let dict = child.value as? [String : AnyObject] {
if let email = dict["email"] {
print(email)
}
}
}
}
}

Related

I am trying to query a firebase database in while the user is typing, but I keep getting this error

So I found this code to query your database while the user is still typing, but the code was outdated and I've been updating it, but there's an error that I don't know how to fix.
func findFriends(text: String) -> Void {
let ref = Database.database().reference()
ref.child("users").queryOrdered(byChild: "username").queryStarting(atValue: text).queryEnding(atValue: text+"\u{f8ff}").observe(.value, with: { snapshot in
let user = User()
let userArray = [User]()
for u in snapshot.children{
user.name = u.value!["name"] as? String
}
})
I get an error in the last line and it says:
Value of type 'Any' has no member 'value'
The elements in snapshot.children are of type Any, which doesn't have a value property. To get at the value property you need to cast u to a DataSnapshot:
for userSnapshot in snapshot.children{
let userSnapshot = userSnapshot as! DataSnapshot
guard let dictionary = userSnapshot.value as? [String: Any] else { return }
user.name = dictionary["name"] as? String
}
Alternatively, you put the cast in the loop:
for userSnapshot in in snapshot.children.allObjects as? [DataSnapshot] ?? [] {
guard let dictionary = userSnapshot.value as? [String: Any] else { return }
user.name = dictionary["name"] as? String
}

Swift: is it possible to iterate and call an array of functions?

I am trying to simplify the following repetitive code:
var cells = [Cell]()
var modules = [Module]()
var fields = [Field]()
root.child("cells").observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String: Any],
let cell = Cell(dict: dict) else { return }
cells.append(cell)
}
root.child("modules").observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String: Any],
let module = Module(dict: dict) else { return }
modules.append(module)
}
root.child("fields").observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String: Any],
let field = Field(dict: dict) else { return }
fields.append(field)
}
Cell, Module, Field are custom struct. I am thinking whether it's possible to put their initiators init?(dict: [String: Any]) in an array and pass in dict to each of them.
I think you will need to make your structs adopt one protocol for that:
protocol InitializableWithDictionary {
init?(dict: [String : Any])
}
struct Cell: InitializableWithDictionary {
//...
init?(dict: [String : Any]){
//...
}
}
struct Module: InitializableWithDictionary {
//...
init?(dict: [String : Any]){
//...
}
}
struct Field: InitializableWithDictionary {
//...
init?(dict: [String : Any]){
//...
}
}
var cells: [InitializableWithDictionary] = [Cell]()
var modules: [InitializableWithDictionary] = [Module]()
var fields: [InitializableWithDictionary] = [Field]()
root.child("cells").observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String: Any] else { return }
let array: [InitializableWithDictionary.Type] = [Cell.self, Module.self, Field.self]
array.forEach {
if let element = $0.init(dict: dict) {
switch element {
case is Cell: cells.append(element)
case is Module: modules.append(element)
case is Field: fields.append(element)
default: break
}
} else { return }
}
}

Can't get node of firebase children

Hi there i'm newest in swift. I am working with a firebase database with at 2 layer of hierarchy as well as many children for each node. I got 1st layer (descript, enddata and other), but i stll can't get the news node. Is in 3 to 5 random keys. I sow many issues but still not have issue for me.
I'm understand i'm doing some wrong but what?
The Firebase is:
i need retreat the news child
struct is
struct ICONews {
let ICOId: String
let news1: String
let news2: String
let news3: String
init?(ICOId: String, dict: [String: Any] ) {
self.ICOId=ICOId
guard let news1 = dict[""] as? String,
let news2 = dict[""] as? String,
let news3 = dict[""] as? String
else { return nil }
self.news1 = news1
self.news2 = news2
self.news3 = news3
}
}
struct NewsSnapShot {
let posts: [ICONews]
init?(with snapshot: DataSnapshot) {
var posts = [ICONews] ()
guard let snapDict = snapshot.value as? [String: [String: Any]] else { return nil }
for snap in snapDict {
guard let post = ICONews (ICOId: snap.key, dict: snap.value) else {continue}
posts.append(post)
}
self.posts=posts
}
}
class of DataBase
class DatabaseService {
static let shared = DatabaseService()
private init(){}
let ICOReference = Database.database().reference()
}
and retreat method
DatabaseService.shared.ICOReference.child("news").observe(DataEventType.value, with: { (snapshot) in
guard let postsSnapShot = ICOSnapShot(with: snapshot) else {return}
})
done
Database.database().reference().observeSingleEvent(of: .value, with: {(snapshot) in
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? DataSnapshot {
let values = (rest as! DataSnapshot).value as? NSDictionary
let enumeratorMap1 = (rest as! DataSnapshot).children
while let rest2 = enumeratorMap1.nextObject() as? DataSnapshot {
let valuesMap1 = (rest2 as! DataSnapshot).value as? NSDictionary
if (rest2 as! DataSnapshot).key == "news" {
print(rest2.value)
}
}
}
})
Make the the Firebase Api call like
Database.database().reference().child("users").child(userID).observe(.childAdded, with: { (snapshot) in
if snapshot.exists() {
let receivedMessage = snapshot.value as! [String: Any]
let name = receivedMessage["name"] as? String ?? ""
let id = receivedMessage["id"] as? Double ?? 0.0
let profileurl = receivedMessage["url"] as? String ?? ""
completion(User(name: name, id: id, url: url))
} else {
failure()
}
})

facing Issue in parsing in swift3

I am trying to parse the emergency data in into emergency struct but it never statifies the condition and get into else case.Here is my code and structure.Some thing i have written woring in first line.
if let emergencyDict = snapshotValue["emergency"] as? [String:[String:Any]]{
for (emerId, emerData) in emergencyDict {
let emer = Emergency.init(emergency: emerData as NSDictionary)
emergency.append(emer)
}
}
else{
let emer = Emergency.init(emerg: "" as AnyObject)
emergency.append(emer)
}
struct Emergency{
var emer_id: String
var emer_name: String
var emer_phoneNo: String
init(emergency: NSDictionary) {
if emergency.object(forKey: "id") != nil {
emer_id = emergency.object(forKey: "id") as! String
}
else{
emer_id = ""
}
}
}
The problem you are having emergency as Array with type [Any] and if you remove the first object then you get Array of type [[String:Any]]. So try like this way.
if let array = snapshotValue["emergency"] as? [Any],
let emergencyArrar = Array(array.dropFirst()) as? [[String:Any]] {
print(emergencyArray)
for emergency in emergencyArray {
print(emergency)
}
}
You have written wrong in this line:
if let emergencyDict = snapshotValue["emergency"] as? [String:[String:Any]]{
It should be:
if let emergencyDict = snapshotValue["emergency"] as? [[String:Any]]{
This question should belong to query from firebase database.
// you have to get the children in emergency,
// then get the value(dictionary) of each child
ref.child("emergency").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let keys = value?.allKeys // [1, 2, 3 ....]
for key in keys {
ref.child("emergency").child(key)..observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
// Here is your dictionary
}
}
}) { (error) in
print(error.localizedDescription)
}

Firebase 2, accesing child values in snapshot produces nulls

I've been attempting to utilize firebase's snapshots, but when I try to access specific children, the output is a null.
var ref = FIRDatabaseReference.init()
func loadData {
ref = FIRDatabase.database().reference(
ref.child("Posts").child(postId).observeSingleEventOfType(.Value, withBlock: { snapshot in
print(snapshot.value?["PostText"] as! String) // Optional(<null>)
print(snapshot)
for child in snapshot.children {
if child.childSnapshotForPath("PostText").value == nil {
self.postText.text = ""
} else {
self.postText.text = child.childSnapshotForPath("PostText").value as? String // Optional(<null>)
print(child.childSnapshotForPath("PostText").value)
}
}
})
}
Output of print(snapshot)
Snap (84844) {
Author = lGAV1KUhSCP8hnFiKY1N9lBPrmmst1;
CommentsCount = 1;
Group = 665555;
ImageUrl = "http://i.telegraph.co.uk/multimedia/archive/03589/Wellcome_Image_Awa_3589699k.jpg";
PostText = "I like cakeh, but theijijijijijij truth is, it's too sweet. So SOMETIMES I dont eat it, but i LIKE CAKE.";
}
It looks like your snapshot is a Dictionary. Then you have to cast it as a Dictionary:
func loadData {
ref = FIRDatabase.database().reference(
ref.child("Posts").child(postId).observeSingleEventOfType(.Value, withBlock: { snapshot in
print(snapshot.value?["PostText"] as! String) // Optional(<null>)
print(snapshot)
let dict = snapshot.value as! Dictionary<String, AnyObject>
if let author = dict["Author"] as? String, commentsCount = dict["CommentsCount"] as? Int, group = dict["Group"] as? Int {
print("author \(author) commentsCount \(commentsCount), group: \(group)")
}
})
}
Do the same for ImageUrl and PostText, they should be cast as String