I have tried many solutions to make this work, but it doesn't seem to work with me. These are the solutions I have tried:
Firebase Retrieving Data in Swift
https://firebase.google.com/docs/database/ios/read-and-write
https://www.raywenderlich.com/187417/firebase-tutorial-getting-started-3
I am trying to retrieve the deviceToken of the currently logged in user, for example if John logs in, it would assign or retrieve his deviceToken and assign it to a variable.
The closest I have got was with this code, but I get every profile with every data stored in that profile instead of the currently logged in one.
let userID = Auth.auth().currentUser?.uid
let ref = Database.database().reference(withPath: "users/profile/\(userID)")
ref.observeSingleEvent(of: .value, with: { snapshot in
if !snapshot.exists() {
return
}
let token = snapshot.childSnapshot(forPath: "deviceToken").value
print(token!)
})
There is an example on the documentation, modifying for your case:
let userID = Auth.auth().currentUser?.uid
ref.child("users").child("profile").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let deviceToken = value?["deviceToken"] as? Int ?? ""
// ...
}) { (error) in
print(error.localizedDescription)
}
Related
This is my firebase database.
I wish to go through my database to grab each ticket's value such as "ignore", "Peter rabbit....", "Incredibles 2....", etc.
Currently I am extracting data like this:
ref = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
ref?.child("users").child(uid!).observe(.childAdded, with: { (snapshot) in
if let userDict = snapshot.value as? [String:String] {
self.movieNameFromTickets.append(myValue)
}
})
But I feel that it isn't a good way to extract data because if I have another structure like tickets, it might print out the wrong information.
What would be a better way to extract my tickets' values?
Thanks :)
Try this :
Database
.database()
.reference()
.child("Users")
.child(Auth.auth().currentUser!.uid)
.child("Advertisements")
.queryOrderedByKey()
.observeSingleEvent(of: .value, with: { snapshot in
guard let dict = snapshot.value as? [String:Any] else {
print("Error")
return
}
// get value from dict here .
})
I've have tried different attempts of retrieving data from firebase (Database), but sadly with no luck :I... So I was wondering If this is the correct way of doing it?
let dBRef = Database.database().reference()
dBRef.child("Users").child("Advertisements").queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
let snapshotValue = snapshot.value as? NSDictionary
let imageAd = snapshotValue?["imageAd"] as? String
let priceAd = snapshotValue?["priceAd"] as? String
Im not sure if I actually receive the data, and Im not sure of how to test this as well... I have tried debugging but with no luck...
So my question is, is my code wrongly done? and if not how do I check If I actually receive the data??
You are observing the childAdded event.
So your closure will only be executed when a new value I inserted into Users/Advertisements.
Try this code instead
Database
.database()
.reference()
.child("Users")
.child(Auth.auth().currentUser!.uid)
.child("Advertisements")
.queryOrderedByKey()
.observeSingleEvent(of: .value, with: { snapshot in
guard let dict = snapshot.value as? [String:Any] else {
print("Error")
return
}
let imageAd = dict["imageAd"] as? String
let priceAd = dict["priceAd"] as? String
})
The closure will be executed only once and "almost" immediately.
to test if your data was pulled in accurately, you can add, below your code: print(imageAd). assuming this code is in viewDidLoad then it will show up in the console when the view controller comes up.
also, I believe .queryOrderedByKey(...) is now .queryOrdered(byKey:...)
keep in mind that .observe() essentially opens a connection to your firebase. if you want a live, realtime connection to stay open and listen for updates to data, this makes sense. if you only need the data once, when you load something, consider using .observeSingleEventOf() instead. if you are going to use .observe() , you should also use .removeAllObservers() to close the connection when you need it to be closed.
it seems like you are just trying to add this info which you've previously set up in your DB. I would do it like this - (keep in mind you were missing the uid step in your json. I have assumed it is the current user in the code below, but if it's a static user, you'd need to define it as a string):
let uid = Auth.auth().currentUser?.uid
dBRef.child(Users).child(uid).child(Advertisements).observeSingleEvent(of:
.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let imageAd = value?["imageAd"] as? String ?? ""
let priceAd = value?["priceAd"] as? String ?? ""
print("imageAd: \(imageAd!)")
print("priceAd: \priceAd!)")`
})
I can see one problem is that your path is wrong. Try something like:
let dBRef = Database.database().reference()
dBRef.child("Users/\(FirAuth.auth.currentUser.uid)/advertisements")
dbRef.queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
I was having the same problem as yours but by looking at the firebase Doc you can see how to retrieve data easily.
lazy var databaseRef = Database.database().reference().child(yourpath).("Advertisements")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
let postDict = snapshot.value as? [String : AnyObject] ?? [:]
if let email = postDict["Email"] {
print(email)
}
}) { (error) in
print(error.localizedDescription)
}
I am trying to get current users firstname from firebase using swift code. Below is my JSON file and swift code. But it's not retrieving first name. Please suggest
Json:
Swift code:
if FIRAuth.auth()?.currentUser != nil{
let queryRef = FIRDatabase.database().reference().child("expatsappmembers")
let userID : String = (FIRAuth.auth()?.currentUser?.uid)!
print("Current user ID is" + userID)
queryRef.child("uid").child(userID).observeSingleEvent(of: .value, with: {(snapshot) in
print(snapshot.value)
let userName = (snapshot.value as! NSDictionary)["firstname"] as! String
print(userName)
})
}
It is slightly different to get a value from Firebase in Swift 3
the proper way to do it is:
ref.child("expatsappmembers").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let firstName = value?["firstname"] as? String
// ...
}) { (error) in
print(error.localizedDescription)
}
Edit, update at bottom, still having issues
I have my users stored in Firebase like this - each user's values are stored under their uid (FIRAuth.auth()?.currentUser?.uid):
"users" : {
"tzfHgGKWLEPzPU9GvkO4XE1QKy53" : {
"gender" : "male",
"handle" : "TestHandle2",
"name" : "Timothy",
"profilePicture" : "https://graph.facebook.com/*removed*/picture?type=large&return_ssl_resources=1"
}
}
Now to get the user's info (to set it to my User object to use around the app), I have this function:
func getUserInfo() {
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users")
// How to get specific user (current user only)??
userRef.observeSingleEvent(of: .value, with: { (snapshot) in
let users = snapshot.value as! [String: Dictionary<String, String>]
for (key, value) in users {
guard let name = value["name"] else {print("Error getting user name"); return}
guard let handle = value["handle"] else {print("Error getting user handle"); return}
guard let gender = value["gender"] else {print("Error getting user gender"); return}
guard let profilePicture = value["profilePicture"] else {print("Error getting user profilePicture"); return}
print("\n\nName: \(name)\nHandle: \(handle)\nGender: \(gender)\nProfile Picture: \(profilePicture)\n\n")
}
})
}
However this returns the values for all the users in the DB - I only want to get the values for the current user.
What can I add/change to this function to ensure that it only retrieves the values for the current user, and not all users? Also (I can make a separate question if necessary but it seems to be relevant here), is this structure of storing each user's values as children of their UID a good way to do it? I noticed a lot of the time in other examples that they are stored under a childByAutoId instead. I'm not sure what advantage that would have.
Thanks for any help!
EDIT:
If I add another child (uid) to the end of the reference and then cast as a [String : AnyObject] dictionary, I can get the current users values, but parsing it seems to be an issue.
func getUserInfo() {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {print("Error getting user UID"); return}
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(uid)
self.currentUser?.uid = uid
userRef.observeSingleEvent(of: .value, with: { (snapshot) in
if let usersDict = snapshot.value as? [String : AnyObject] {
print(usersDict)
for user in usersDict {
// guard let name = user.value(forKey: "name") else {print("Error getting user name"); return}
// guard let handle = user.value(forKey: "handle") else {print("Error getting user handle"); return}
// guard let gender = user.value(forKey: "gender") else {print("Error getting user gender"); return}
// guard let profilePicture = user.value(forKey: "profilePicture") else {print("Error getting user profilePicture"); return}
// print("\n\nName: \(name)\nHandle: \(handle)\nGender: \(gender)\nProfile Picture: \(profilePicture)\n\n")
}
}
})
}
I get an error on each of the user.value(forKey) lines, stating "cannot call value of non-function type AnyObject".
If I print(user.value) inside the loop I get all of the current user's values back perfectly. I just can't specify them individually.
You need to add another child to your userRef
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(uid)
First get UID of the current user,
let currentUid = FIRAuth.auth()?.currentUser?.uid
then replace this database reference,
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users")
with this,
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(currentUid)
:-)
it's easier than you think :-)
let userRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(FIRAuth.auth()?.currentUser?.uid)
Here's how I do my load of the users info,
First, I created a NSObject Class called User...
import UIKit
class User: NSObject {
// Add Whatever Child values of the user you have here
var email: String?
var nickname: String?
}
Then I called
func GetUserInfo() {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
FIRDatabase.database().reference().child("users").child(uid)
.observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.setValuesForKeys(dictionary)
print(user.nickname!)
}, withCancel: nil)
}
Don't know if this helps or not..
I'm trying to retrieve specific data from just the currently logged in user. My data in my database looks like this:
For example, I want to just grab the full_name and save it in a variable userName. Below is what I'm using to grab my data
ref.queryOrderedByChild("full_name").queryEqualToValue("userIdentifier").observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
print(snapshot.value)
// let userName = snapshot.value["full_name"] as! String
})
Unfortunately, this is what my console prints.
I would appreciate any help :) Thank you!
It gives you that warning message indexOn because you are doing a query.
you should define the keys you will be indexing on via the .indexOn
rule in your Security and Firebase Rules. While you are allowed to
create these queries ad-hoc on the client, you will see greatly
improved performance when using .indexOn
As you know the name you are looking for you can directly go to that node, without a query.
let ref:FIRDatabaseReference! // your ref ie. root.child("users").child("stephenwarren001#yahoo.com")
// only need to fetch once so use single event
ref.observeSingleEventOfType(.Value, withBlock: { snapshot in
if !snapshot.exists() { return }
//print(snapshot)
if let userName = snapshot.value["full_name"] as? String {
print(userName)
}
if let email = snapshot.value["email"] as? String {
print(email)
}
// can also use
// snapshot.childSnapshotForPath("full_name").value as! String
})
Swift 4
let ref = Database.database().reference(withPath: "user")
ref.observeSingleEvent(of: .value, with: { snapshot in
if !snapshot.exists() { return }
print(snapshot) // Its print all values including Snap (User)
print(snapshot.value!)
let username = snapshot.childSnapshot(forPath: "full_name").value
print(username!)
})
{
"rules": {
"tbl_name": {
".indexOn": ["field_name1", "field_name2"]
},
".read": true,
".write": true
}
}
You can apply indexOn on any field. Add this json in rules security and rules tab.
Hope this works for you. :)
It retrieves logged in user data:
let ref = FIRDatabase.database().reference(fromURL: "DATABASE_URl")
let userID = FIRAuth.auth()?.currentUser?.uid
let usersRef = ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot)
let ref = Database.database().reference().child("users/stephenwarren001#yahoo.com")
ref.observeSingleEvent(of: .value, with: { (snap : DataSnapshot) in
print("\(String(describing: snap.value))")
}) { (err: Error) in
print("\(err.localizedDescription)")
}
var refDatabase = DatabaseReference()
refDatabase = Database.database().reference().child("users");
let refUserIdChild = refDatabase.child("stephenwarren001#yahoo.com")
refUserIdChild.observeSingleEvent(of: .value, with: { snapshot in
if !snapshot.exists() { return }
print(snapshot) // Its print all values including Snap (User)
print(snapshot.value!)
if let tempDic : Dictionary = snapshot.value as? Dictionary<String,Any>
{
if let userName = tempDic["full_name"] as? String {
self.tfName.text = userName
}
if let email = tempDic["email"] as? String {
self.tfEmail.text = email
}
}
})