Retrieving only current user's child values from Firebase - ios

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..

Related

swift 3 firebase snapshot if value equal to ... fetch

I'm Trying to check if the rooms's value 'Owner' equals to the current user id if so then fetch all data including the key value and continue checking other children of 'rooms'
I was trying, but I fail finding the solution though it might seem easy so please help me with your suggestions or ideas. My code so far :
Database.database().reference().child("rooms").queryOrdered(byChild: "Owner").observeSingleEvent(of: .value, with: { (snapshot) in
let currentUser = Auth.auth().currentUser?.uid
if !snapshot.exists() {
print("No data found")
return
}
var rooms = snapshot.value as! [String:AnyObject]
let roomKeys = Array(rooms.keys)
for roomKey in roomKeys {
guard
let value = rooms[roomKey] as? [String:AnyObject]
else
{
continue
}
let title = value["title"] as? String
let description = value["description"] as? String
let roomPictureUrl = value["Room Picture"] as? String
let longitude = value["Longtitude"] as? String
let latitude = value["Latitude"] as? String
let dateFrom = value["Date From"] as? String
let dateTo = value["Date To"] as? String
let owner = value["Owner"] as? String
let myRooms = Room(roomID: roomKey,title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
self.rooms.append(myRooms)
self.tableView.reloadData()
print(snapshot.value)
}
})
You're missing the value in your query:
Database.database().reference()
.child("rooms")
.queryOrdered(byChild: "Owner")
.queryEqual(toValue: "STbz...")
.observeSingleEvent(of: .value, with: { (snapshot) in
See for this and more query operators, the documentation on filtering data.
Mark:- Swift 5
Database.database().reference().child("user")
.queryOrdered(byChild: "UserPhoneNumber") //in which column you want to find
.queryEqual(toValue: "Your phone number or any column value")
.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.childrenCount > 0
{
if let snapShot = snapshot.children.allObjects as? [DataSnapshot] {
//MARK:- User Exist in database
for snap in snapShot{
//MARK:- User auto id for exist user
print(snap.key)
break
}
}
}
else if snapshot.childrenCount == 0
{
//MARK:- User not exist no data found
}
})

How to retrieve data from current User in Firebase using Swift?

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)
}

Firebase NSNull Exception while taking Snapshot of Data

i was making a Firebase practice app and i encountered this problem. Where i got NSNull exception while capturing a value from Firebase database. Here is the code
user = FIRAuth.auth()?.currentUser
ref = FIRDatabase.database().reference()
let userid = user.uid
if userid != nil
{
print("User Nid \(userid)")
ref.child("users").child(userid).observe(.value, with: {
(snapshot) in
if(snapshot.exists()){
var user_details = snapshot.childSnapshot(forPath: "\(userid)")
var user_det = user_details.value as! Dictionary<String, String>
print("User Name \(user_det["name"])")
}
else{
print("Does not exist")
}
})
}
and here is the database.
uid
user-details
name: "Salman"
propic: "picurl"
Could you try with this way
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
if let userDetail= value?["user-details"] as? [String:Any] {
// let username = value?["name"] as? String ?? ""
let username = userDetail["name"] as? String ?? ""
}
}) { (error) in
print(error.localizedDescription)
}

Two arrays of the same type, one getting updated and the other is nil

I have two arrays, one in a view controller (var usersRooms: [Room] = []), and the other in a User object (var rooms: [Room] = []). There's a reference to the object in the view controller (var currentUser: User?). A you can see, both arrays are of type [Room].
In the function below I make a call to Firebase to retrieve the user's info and set the User object.
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)
let userRoomRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(uid).child("rooms")
self.currentUser?.uid = uid
userRef.observeSingleEvent(of: .value, with: { (snapshot) in
if let usersDict = snapshot.value as? NSDictionary {
print("\n\nUserDict: \(usersDict)\n\n")
guard let name = usersDict["name"] as? String else {print("Error getting user's name"); return}
guard let handle = usersDict["handle"] else {print("Error getting user's handle"); return}
guard let gender = usersDict["gender"] else {print("Error getting user's gender"); return}
guard let profilePicture = usersDict["profilePicture"] else {print("Error getting user's profilePicture"); return}
// how to get user's rooms from FB and add into User object's rooms array??
userRoomRef.observeSingleEvent(of: .value, with: { (roomSnap) in
for eachRoom in roomSnap.value as! [String : AnyObject] {
let roomID = eachRoom.key as! String
userRoomRef.child(roomID).observeSingleEvent(of: .value, with: { (roomSnap) in
if let roomInfo = roomSnap.value as? [String : AnyObject] {
guard let roomName = roomInfo["roomName"] as! String! else {print("Error getting room name"); return}
guard let participants = roomInfo["participants"] as! [String]! else {print("Error getting room participants"); return}
print("\n\nRoom Name: \(roomName)\nRoom Participants: \(participants)\nRoom ID: \(roomID)\n")
self.usersRooms.append(Room(id: roomID, name: roomName, participants: participants))
self.currentUser?.rooms.append(Room(id: roomID, name: roomName, participants: participants))
print("\n\nUser's Rooms: \(self.usersRooms)\n\n")
print("\n\nRooms (from currentUser): \(self.currentUser?.rooms)\n\n")
}
})
}
})
print("\nRoomsTableViewController User Values:\n\nName: \(name)\nHandle: \(handle)\nGender: \(gender)\nProfile Picture: \(profilePicture)\n\n")
self.currentUser?.handle = handle as! String
self.currentUser?.name = name
self.senderDisplayName = name
self.currentUser?.profilePicture = profilePicture as! String
self.currentUser?.gender = gender as! String
}
})
}
In that function, I tried to append both arrays, exactly the same way, as a test:
self.usersRooms.append(Room(id: roomID, name: roomName, participants: participants))
self.currentUser?.rooms.append(Room(id: roomID, name: roomName, participants: participants))
When I printed them on the next line, the usersRooms array was full of the Room objects as intended. However the array in User, currentUser.rooms, was nil. It's still nil even if I try to say self.currentUser?.rooms = self.usersRooms.
Why is it that I can set the usersRooms array but not the same array in my object?

Firebase Retrieving Data in Swift

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
}
}
})

Resources