I was trying to initialize the values in the User object but from another question it seems like it's not possible to do it there - now, trying to do the same thing in a view controller in viewDidLoad, I'm running into another error:
This is my call to Firebase in viewDidLoad (myUser is a global variable var myUser:User!):
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").childByAutoId()
let userRefHandle: FIRDatabaseHandle?
userRefHandle = userRef.observe(.value, with: { (snapshot) -> Void in
let userData = snapshot.value as! Dictionary<String, AnyObject>
let id = snapshot.key
if (FIRAuth.auth()?.currentUser?.uid) != nil {
if let name = userData["name"] as! String!, name.characters.count > 0 {
let handle = userData["handle"] as! String!
let gender = userData["gender"] as! String!
let profilePicture = userData["profilePicture"] as! String!
let uid = userData["uid"] as! String!
// let rooms = userData["rooms"] as! [[String : AnyObject]]
myUser.uid = uid
myUser.uid = handle
myUser.uid = name
myUser.uid = profilePicture
myUser.uid = gender
// myUser.rooms = rooms
} else {
print("Error! Could not initialize User data from Firebase")
}
}
})
The end goal for this is so that when a user launches the app (already signed up and their info is in Firebase), their info is pulled from the database and set to the User object so the values can be used around the app (name, handle, profilePicture, etc.).
I'm getting the error: Could not cast value of type 'NSNull' (0x106d378c8) to 'NSDictionary' on the let userData = snapshot.value line.
This is what the user's data looks like in Firebase:
"users" : {
"-KgjW9PEvCPVqzn7T5pZ" : {
"gender" : "male",
"handle" : "TestHandle123",
"name" : "Timothy",
"profilePicture" : "https://graph.facebook.com/*removed*/picture?type=large&return_ssl_resources=1",
"uid" : "2q4VCKu1e7hiL84ObdzgQcQ0pH63"
}
}
I'm wondering if this is the correct way to set a user's values from Firebase, and if so, how to avoid the error?
in your code, you are looking for the profile picture using profile
let profilePicture = userData["profile"] as! String!
but in the data, you have profilePicture
Because you have forced the unwrap you will get this error when the key is not found.
You should make sure that you use the same key in both places. It might also be worth including defaults in case you ever have data issues
let profilePicture = userData["profile"] as? String ?? "default"
Since the user is already signed up you should store the key that references to the firebase user (e.g. via NSUserDefaults). In this case "-KgjW9PEvCPVqzn7T5pZ". Use this in the userRef instead of childByAutoId, which would generate a new child location with a new key and doesn't exists yet (hence the NSNull).
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child("-KgjW9PEvCPVqzn7T5pZ")
Related
I have code which retrieves users from firebase. The problem is that I get the error:
Ambiguous use of 'subscript'
On the lines, I marked in the block below. The weird thing is that the exact same code is currently in another project in nearly identical circumstances and it does not get this error.
The code is below:
func retriveUsers() {
let ref = Database.database().reference()
ref.child("user2").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
let users = snapshot.value as! [String : AnyObject]
self.users.removeAll()
for (_, value) in users {
if let uid = value["uid"] as? String {//Error
if uid != Auth.auth().currentUser?.uid {
let userToShow = User()
if let fullName = value["full name"] as? String {//Error
userToShow.fullName = fullName
userToShow.userID = uid
self.users.append(userToShow)
}
}
}
}
})
print(users.count, " This is the number of users retrived the first looks like: ", users[0].userID)
}
I have looked here and here and neiother has solved my problem. What is the solution here?
The compiler doesn't know the type of value in users, you provided AnyObject which is ambiguous because it can be both an array (index subscripted) or dictionary (key subscripted).
Be more specific and tell the compiler that value is a dictionary, by the way it's always supposed to be Any not AnyObject and check the type safely
if let users = snapshot.value as? [String : [String:Any]] { ...
Im currently trying to implement a leaderboard in my app using a UITableView and a Firebase Database backend, I need to be able to sort data according to highest score and display the Username and score accordingly. The current code doesn't retrieve data and uses the optional default values that are coded.
func retrieveScores(){
_ = Auth.auth().currentUser?.uid
let highScoreDB = Database.database().reference().child("Leaderboard").child("True False Quiz").queryOrdered(byChild: "High Score")
highScoreDB.observeSingleEvent(of: .value) { (snapshot) in
let value = snapshot.value as! Dictionary<String, Any>
print(value)
let userName = value["Name"] as? String ?? "error"
let highScore = value["High Score"] as? Int ?? 0
print(highScore)
let score = HighScore()
score.name = userName
score.score = highScore
self.scoreArray.append(score)
self.highScoreTableView.reloadData()
}
}
This is the function that retrieves user data and then passes it into an array where the table view can access the data.
The console currently prints:
["ZybxNO7fQeMHEkc2CnCq74xsmus1": {
"High Score" = 9;
Name = ty;
}, "kLxqZteRfBeC0bNIkLCjrPukMGx1": {
"High Score" = 11;
Name = Sam;
}]
which is the data being retrieved from the database, but this data is not appended and the app displays the following:
App View
Thanks in advance.
If you request the result of a query as a value, you get a single snapshot that has all the nodes that match your query. To get to each individual node, you need to loop over the children of that snapshot:
highScoreDB.observeSingleEvent(of: .value) { (snapshot) in
for score in snapshot.children.allObjects as! [DataSnapshot] {
let value = score.value as! Dictionary<String, Any>
print(value)
let userName = value["Name"] as? String ?? "error"
let highScore = value["High Score"] as? Int ?? 0
print(highScore)
let score = HighScore()
score.name = userName
score.score = highScore
self.scoreArray.append(score)
}
self.highScoreTableView.reloadData()
}
Your value have other structure than you're waiting for.
Seems like your firebase model looks like
{
<some_key>: {
"Name": String,
"High Score": Int
}
}
You're trying now to get "Name" of the value you just obtained and you won't reach this until your model has look like now.
Firstly you have to get value for your key and THEN get your "Name" and "High Score".
I have looked around for a while, with no luck. I need to get the string value of a certain dictionary key in firebase.
If you look at the image below,I need that key on top, and need to set it equal to a string, that I can segue to other viewcontrollers so when a user wants to make a post under the sharers for example, I go into the right value based on the key, then to sharers, where I can add values. Thanks, also I do not need all values, just once I have observedWithSingleEvent, I need to get the key of each page or dictionary.
my code:
let ref = FIRDatabase.database().reference()
ref.child("Notes").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
if let pagers = snapshot.value as? [String : AnyObject] {
let numb = snapshot.key //what I want
for (_, val) in pagers {
if let useri = val["postUsername"] as? String {
if useri == FIRAuth.auth()?.currentUser?.uid {
let bindfl = Page()
if let title = val["title"] as? String, let descript = val["description"] as? String,
let sharers = val["sharers"] as? [String], let poster = val["postUsername"] as? String, let setter = val["setter"] as? String, let creatorName = val["creatorName"] as? String {
bindfl.title = title
bindfl.descriptions = descript
bindfl.setter = setter
bindfl.sharers = sharers
bindfl.usernameOfBinder = poster
bindfl.creatorName = creatorName
bindfl.theBit = numb
self.pages.append(bindfl)
Well you can do it like this, when you add data to the database
let key = ref.("Notes").childByAutoId().key
let notes = ["userName": userName,
"description": description,
"title": title,
"author": author,
"keyID": key]
let childUpdates = ["/Notes/\(key)": notes]
ref.updateChildValues(childUpdates)
After that you can, get the key like this
bindfl.title = title
bindfl.descriptions = descriptions
bindfl.userName = userName
bindfl.author= author
bindfl.keyID= keyID
Hope it worked.
ref.child("Notes"). observeSingleEvent(of: .childAdded, with: {snapshot in
print("\(snapshot.key)")
})
Will give you the autoID key of every entry in the table
ref.child("Notes").queryOrdered(byChild: "creatorName").queryEqual(toValue: "posterName").observeSingleEvent(of: .childAdded, with: {snapshot in
var postID = snapshot.key
//update post different post using retrieved ID
let infoToAdd = ["newPostStuff" : true]
FIREBASE_REF!.child("Posts/\(postID)").updateChildValues(infoToAdd)
})
Will give you the auto ID of every post by a given creator and then update values on a different table with the retrieved key
I have been pondering for the longest time in my student programmer life. I would like to know
I added the keys using autoChildId.
How to get keys from firebase database swift 2? I know how to get from Android using .getKeys()
My best friend, Google, taught me to use allKeys. However, my friendship is on the verge of in despair right now as I received the following msg that our relationship with .allKeys will always fail ( see image below). Haish...
I need this in order to show the data from Firebase Database into my tableview cos I believe this is the issue to a empty table just like how my heart is for my project. No heart.
Here is how my firebase database looks like:
Here is my code:
func findPlaceToEat(){
print("inside findPlaceToEat()")
print("Plan price level")
print(planPriceLevel)
print("End of price level")
ref = FIRDatabase.database().reference()
ref.child("places_detail").child("price_level").child(planPriceLevel).observeEventType(.ChildAdded, withBlock:{
(snapshot) in
if let dictionary = snapshot.value?.allKeys! as? [String: AnyObject]{
let PlaceObj = placeObj(place_name: dictionary["place_name"] as! String, place_type: dictionary["place_type"] as! String, price_range: dictionary["price_range"] as! String, vegan_type:dictionary["vegan_type"] as! String , website: dictionary["website"] as! String)
print("Whatever")
print(PlaceObj);
//self.tableView.reloadData()
}
}, withCancelBlock: nil)
}
to get key from snapshot
snapshot.key
I got a workaround for my project, everyone please pray that my lecturer don't see this. :
What I did was inside the save button I retrieve the value from database and then save it back into Firebase Database.
ref = FIRDatabase.database().reference()
ref.child("hello").child("google! I need a part time job").child(planPriceLevel).observeEventType(FIRDataEventType.ChildAdded, withBlock:{
(snapshot: FIRDataSnapshot) in
if let dictionary = snapshot.value as? [String: AnyObject]{
let getPlaceObj = placeObj()
getPlaceObj.setValuesForKeysWithDictionary(dictionary)
self.PlaceObj.append(getPlaceObj)
print("Name " ,getPlaceObj.place_name)
}
let place_name = snapshot.value?.objectForKey("place_name") as! String
let place_type = snapshot.value?.objectForKey("place_type") as! String
let price_range = snapshot.value?.objectForKey("price_range") as! String
let vegan_type = snapshot.value?.objectForKey("vegan_type") as! String
let website = snapshot.value?.objectForKey("website") as! String
print(place_name, place_type, price_range, vegan_type, website)
let savePlan : [String: AnyObject] = ["place_name":place_name, "place_type":place_type, "price_range":price_range, "vegan_type":vegan_type, "website":website]
self.ref.child("can you place hire me as your intern? I am from Singapore!!!").child(self.user!.uid).childByAutoId().setValue(savePlan)
}, withCancelBlock: nil)
You need to define query orderbykey like bellow:
this.afd.list('/yourItems/', {query:{orderByKey :true}}).subscribe((elements) => {
elements.map(element=>{
console.log(element.$key);
})
});
When listening to a new object in Firebase, I get this error: Could not cast value of type NSTaggedPointerString to NSDictionary. Here is the code that listens to a a user that has registered.
FIRAuth.auth()!.addStateDidChangeListener { auth, user in
guard let user = user else { return }
self.user = User(authData: user)
let userref = FIRDatabase.database().reference(withPath: "users").child(self.user.uid)
userref.observe(.value, with: { snapshot in
print(snapshot.value!)
var newItems: [UserItem] = []
for item in snapshot.children {
let userDetail = UserItem(snapshot: item as! FIRDataSnapshot) /////////// CRASHES HERE //////////
newItems.append(userDetail)
}
self.userItem = newItems
})
print(self.user.uid)
}
And when the error comes up it points to here:
init(snapshot: FIRDataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String:Any] ///// ERROR HERE
name = snapshotValue["name"] as! String
email = snapshotValue["email"] as! String
age = snapshotValue["age"] as! String
ref = snapshot.ref
}
The console is printing what is inside Firebase correctly and the data is there and it exists, but this casting or data read error keeps happening. It has something to do with the conversion but I'm not exactly sure.
Say
snapshot.value as! String
In this case, the value is a string, so that is what you must cast to.
it might be the case that you updated your database and the old data did not have the correct format, try deleting your database, add new data and run your program again