I want to get parent of a child, for do search by users in my app. How can i do that? User will enter full nickname of another user and app will give profile of this user. I understand how to find this user, but how to get UID of this user. Any ideas how can i get uid?
"app"
"users"
"UID"
"name:"
"email:"
"nickname:"
"uid:"
You can easily find all users whose nickname is myNickName:
let userRef = self.ref.child("users")
let query = userRef.queryOrdered(byChild: "nickname").queryEqual(toValue: myNickName)
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
let dict = snap.value as! [String: Any]
let email = dict["email"] as? String ?? ""
print(key)
}
})
Related
In my Firebase Realtime Database, I have a node labelled "groups" and this is how I constructed it:
Underneath the "users" above, I'm trying to use those userIds to reference the data within each user. This is how I constructed each "users" node I'm trying to reference:
In the below code snippet, I get the userIds from a snapshot of the groups' users child node. And then I run a for-in loop on those userIds to access the information in the "users" node.
The print("This should be the individual userId: ", userId) statement prints out each userId correctly. And the userRef.observeSingleEvent(of: .value, with: { (snapshot) in gets called the first time the for-in loop is called, but it's almost like it's ignored. The app crashes because the user array comes up empty at the end. However, a ridiculous amount of empty users show up in the array (when looking at the Variables View in the Debug Area). So, i feel like I'm running some form of a redundant loop or something.
guard let groupChatPartnerId = message.chatPartnerId() else {
return
}
var users: [User]?
let ref = Database.database().reference().child("groups").child(groupChatPartnerId)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
let groupId = snapshot.key
let groupName = snapshot.childSnapshot(forPath: "groupName").value as! String
let userIdDictionary = snapshot.childSnapshot(forPath: "users").value as! Dictionary<String,AnyObject>
let userIds = Array(userIdDictionary.keys)
print("userIds: ", userIds)
for userId in userIds {
print("This should be the individual userId: ", userId)
let userRef = Database.database().reference().child("users").child(userId)
userRef.observeSingleEvent(of: .value, with: { (snapshot) in
print("This is the snapshot: ", snapshot)
let email: String = snapshot.childSnapshot(forPath: "email").value as! String
print("user's email: ", email)
let uid = snapshot.key
let username = snapshot.childSnapshot(forPath: "username").value as! String
let profileImageUrl = snapshot.childSnapshot(forPath: "profileImageUrl").value as! String
let user = User(uid: uid, userUsername: username, userProfileImageUrl: profileImageUrl, userEmail: email)
users?.append(user)
print("user to append to users: ", user)
}, withCancel: nil)
}
print("users :", users)
let group = Group(groupId: groupId, groupName: groupName, users: users!)
self.showChatControllerForGroup(group: group)
}, withCancel: nil)
Let me know if you need any other information. Thanks in advance!
All data is loaded from Firebase asynchronously By the time your print users, none of the userRef.observeSingleEvent has completed yet. So the code to print all users must be inside the completion handle of userRef.observeSingleEvent and must only run once all users have been loaded.
A simple way to do that is to compare the length of users with the length of userIds. If they're the same, you've loaded all users:
for userId in userIds {
print("This should be the individual userId: ", userId)
let userRef = Database.database().reference().child("users").child(userId)
userRef.observeSingleEvent(of: .value, with: { (snapshot) in
print("This is the snapshot: ", snapshot)
let email: String = snapshot.childSnapshot(forPath: "email").value as! String
print("user's email: ", email)
let uid = snapshot.key
let username = snapshot.childSnapshot(forPath: "username").value as! String
let profileImageUrl = snapshot.childSnapshot(forPath: "profileImageUrl").value as! String
let user = User(uid: uid, userUsername: username, userProfileImageUrl: profileImageUrl, userEmail: email)
users?.append(user)
print("user to append to users: ", user)
if userIds.count == users.count {
print("users :", users)
}
}, withCancel: nil)
}
My db structure is in my iOS app
I need to retrieve all fridges that the current user's id and display in a table view. After browsing through all threads for a good amount of time I haven't got the right answer.
Here is my Swift code that doesn't do what I need. I believe I am messing up with queries:
let fridgeDB = Database.database().reference()
let fridgeDBRef = fridgeDB.child("fridges")
guard let uid = Auth.auth().currentUser?.uid else {return}
let queryRef = fridgeDBRef.queryOrdered(byChild: uid)
queryRef.observe(.childAdded) { snapshot in
let snapshotValue = snapshot.value as! Dictionary<String,AnyObject>
print("snapshotValue: \(snapshotValue)")
let name = snapshotValue["FridgeName"]!
let fridge = Fridge()
fridge.fridgeName = name as! String
self.fridgeUnits.append(fridge)
self.configureTableView()
self.fridgeList.reloadData()
You are pretty close.
Your query needs to do two things 1) define the node to query on, and 2) define what your want to query for.
The node you want to query on is actually the uid, and you want to query to see if it's true.
let itemsRef = self.ref.child("fridges")
let thisUserQuery = itemsRef.queryOrdered(byChild: uid).queryEqual(toValue: true)
thisUserQuery.observeSingleEvent(of: .value, with: { snapshot in
guard let foundFridges = snapshot.children.allObjects as? [DataSnapshot] else {return}
for fridge in foundFridges {
let name = fridge.childSnapshot(forPath: "FridgeName").value as! String
print(fridge.key, name)
}
})
I'm trying to retrieve all user's firstnames in my Firebase database. What is the best way to add them to an array?
Firebase database
-Users
-UserId1
- firstname: James
-UserId2
- firstname: Jennifer
Swift code
let rootRef = Database.database().reference()
let query = rootRef.child("Users").queryOrdered(byChild: "firstname")
query.observeSingleEvent(of: .value) {
(snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
let value = snapshot.value as? NSDictionary
let firstname = value?["firstname"] as? String ?? ""
print(firstname)
}
}
Might just be a typo ;) You should be using child inside your loop instead of snapshot. For instance, try replacing the following line:
let value = snapshot.value as? NSDictionary
with:
let value = child.value as? NSDictionary
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 am trying to fetch all the driveways which belongs to user using their email as the search key.
And here is the code I am writing:
guard let currentUser = FIRAuth.auth()?.currentUser else {
return
}
let query = FIRDatabase.database().reference(withPath :"driveways").queryEqual(toValue: currentUser.email!, childKey: "email")
query.observe(.value, with: { (snapshot) in
print(snapshot)
})
How can I get all the driveways based on user's email address?
Try this (Swift 3 Firebase 3)
let email = "johndoe#gmail.com"
let queryRef = drivewaysRef.queryOrdered(byChild: "email")
.queryEqual(toValue: email)
queryRef.observeSingleEvent(of: .value, with: { snapshot in
for snap in snapshot.children {
let driveSnap = snap as! FIRDataSnapshot
let driveDict = driveSnap.value as! [String:AnyObject] //driveway child data
let city = driveDict["city"] as! String
let state = driveDict["state"] as! String
print("email: \(email) city: \(city) state: \(state)")
}
})