retrieving data from auto id database child - swift

I'm kinda new on swift programming, my case is:
I have a database on firebase realtime "see picture", I want to retrieve the firstName and lastName data of a specific ID only.
for example:
When i'm at login screen and logged in using this email: "ali_y_k#hotmail.com", and when going to the next screen i want to display the firstName and lastName of this email in the text fields showing on picture
I have tried several solutions but the problem always was I can't enter the random IDs child to fetch the firstName and lastName
there is what i tried:
First
func retriveInfo () {
let databaseRef = Database.database().reference().child("User_Informations")
databaseRef.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String,String>
let firstName = snapshotValue["firstName"]!
let lastName = snapshotValue["lastName"]!
let email = snapshotValue["email"]!
print(firstName,lastName,email)
}
}
This is printing all data (firstName,lastName,email) from every id
Second
func retriveInfo() {
let databaseRef = Database.database().reference().child("User_Informations")
databaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
for snap in snapshot.children {
let userSnap = snap as! DataSnapshot
let uid = userSnap.key //the uid of each user
let userDict = userSnap.value as! [String:AnyObject] //child data
let firstName = userDict["firstName"] as! String
let lastName = userDict["lastName"] as! String
print("key = \(uid) First Name = \(firstName), Last Name = \(lastName)")
}
})
This will print every key "Id" and all the info
Thank You in advance :)

Since you have childByAutoId you have to use query ordered and query equal.
let reference = Database.database().reference().child("User_Informations").queryOrdered(byChild: "email")
reference.queryEqual(toValue: "ali_y_k#hotmail.com").observeSingleEvent(of: .childAdded) { (snapshot) in
let dictionary = snapshot.value as! [String : Any]
let firstName = dictionary["firstName"]
print(firstName)
}

You need to use the current user id after you login
let currentUserUid = FIRAuth.auth()!.currentUser!.uid
let databaseRef = Database.database().reference().child("User_Informations/\(currentUserUid)")
databaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
}

Related

Cant fetch from Firebase Realtime Database

I don't know why cant find how get friends Ids.
her is my code:
func fetchUsers() {
let ref = Firebase.Database.database().reference()
guard let userId = Auth.auth().currentUser?.uid else { return }
let userID = userId
ref.child("Users").child(userID).observe(.childAdded) { (snapshot) in
print("snapshot...\(snapshot)")
let user = User()
if let dictionary = snapshot.value as? [String:AnyObject]{
user.currentUserFriends = dictionary["Friends"] as? String
print("dictionary...\(user.currentUserFriends ?? "no value")")
}
}
}
and my tree from firebase is Users-Uid-Friends-friendID-true.
Solved!
ref.child("Users").child(userID!).child("Friends").observeSingleEvent(of: .value) { (snapshot) in
print("snapshot...\(snapshot)")
let dic = snapshot.value as! NSDictionary
for (key,value) in dic{
let friendsID = key
let friendBool = value
print("key is \(friendsID) and value is \(friendBool)")
let user = User()
user.currentUserFriends = key as? String
}
}

Not able to read data from Firebase realtime database

I have stored the comments under a post in firebase realtime database. The problem i have is that when i try to parse out the data from firebase i get an error that says Unexpectedly found nil while unwrapping an Optional value. So for example if i try to pront the data stored under degree, i get this nil error. But when i print "comments" instead of the "degree" i successfully fetch the data. My database structure looks like this.
func obeserveComments() {
// get auto-id of post
let commentKey = self.keyFound
let postRef = Database.database().reference().child("posts").child(commentKey)
var tempComments = [Comments]()
postRef.observe(.value, with: {(snapshot) in
if let dict = snapshot.value as? [String:Any] {
if let comments = dict["comments"] as? [String:Any] {
let degree = comments["reply degree"] as! String
// let name = comments["reply name"] as! String
// let text = comments["reply text"] as! String
// let university = comments["reply university"] as! String
// let photoURL = comments["reply url"] as! String
// let url = URL(string: photoURL)
// let timestamp = comments["timestamp"] as! Double
print(degree)
}
}
})
}
The answer by #aytroncb is a good answer, I prefer to leave Firebase data 'Firebasy' as long as possible. In other words coverting to dictionaries looses ordering and and find code like this
[String: [String: [String: Any]]]
To be very hard to read.
I prefer
let snap = snapshot.childSnapshot("comments") //snap becomes a DataSnapshot
So my solution maintains the order and leverages .childSnapshot to leave data in it's DataSnapshot form.
func readPostComments() {
let postRef = self.ref.child("posts") //self.ref points to my firebase
postRef.observeSingleEvent(of: .value, with: { snapshot in
let allPosts = snapshot.children.allObjects as! [DataSnapshot]
for postSnap in allPosts {
print("postId: \(postSnap.key)")
let commentsSnap = postSnap.childSnapshot(forPath: "comments") //will be a DataSnapshot
let allComments = commentsSnap.children.allObjects as! [DataSnapshot]
for commentSnap in allComments {
print(" commentId: \(commentSnap.key)")
let replyDegree = commentSnap.childSnapshot(forPath: "reply_degree").value as? String ?? "No Degree"
let replyName = commentSnap.childSnapshot(forPath: "reply_name").value as? String ?? "No Name"
print(" degree: \(replyDegree) by: \(replyName)")
}
}
})
}
EDIT
For a single post, remove the top part of the code that reads in and iterates over all posts.
func readCommentsForOnePost() {
let postRef = self.ref.child("posts")
let postCommentRef = postRef.child("post_0")
postCommentRef.observeSingleEvent(of: .value, with: { snapshot in
print("postId: \(snapshot.key)")
let commentsSnap = snapshot.childSnapshot(forPath: "comments") //will be a DataSnapshot
let allComments = commentsSnap.children.allObjects as! [DataSnapshot]
for commentSnap in allComments {
print(" commentId: \(commentSnap.key)")
let replyDegree = commentSnap.childSnapshot(forPath: "reply_degree").value as? String ?? "No Degree"
let replyName = commentSnap.childSnapshot(forPath: "reply_name").value as? String ?? "No Name"
print(" degree: \(replyDegree) by: \(replyName)")
}
})
}
Its because firebase is returning your data like this
{
"MAKFW244kdL)Cw;1": [Array of data],
"LOPSw!35pa3flAL4": [Array of data],
"ALV34VR4_A6Vn1a": [Array of data]
}
So change your initial casting of snapshot.value to this:
if let dict = snapshot.value as? [String: [String: Any]]
then loop through that new dictionary like this:
for objectJson in dict.values {
if let comments = objectJson["comments"] as? [String: [String: Any]] {
for commentJson in comments.values {
let degree = commentJson["reply_degree"] as? String
}
}
}
Update
Just read through your post again and noticed your trying to access the comments directly with a key, your first going to need to provide the PostId. Then you can use the above code to loop through the objects
let postRef = Database.database().reference().child("posts").child(postID)
alternatively I believe you can have the comments returned as a normal list by doing something like this:
let postRef = Database.database().reference().child("posts").child("\(postID)/{id}")

Get Dictionary of Users Uid on Firebase

This is my case; I need a dictionary of all of the users in my app to use didSelectRowAt on a UITableView to get the searched users uid.
my firebase database is designed like this:
not allowed to upload Images so link here
Also, I succesfully made a string/dictionary of the users names by doing this;
let rootRef = Database.database().reference()
let query = rootRef.child("users").queryOrdered(byChild: "users")
query.observe(.value) { (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let value = child.value as? NSDictionary {
// declaring a user in class User() which was made with strings(name, email, ect.)
let user = User()
let name = value["name"] as? String ?? "name not found"
// making the string of it go into the user.name
user.name = name
// appending it into a variable of class user()
self.users.append(user)
}
}
}
I'm not sure how to do this because the uid's are all different and don't have a name to it (ex. email: test#test.com).
Perhaps I need to restructure my database to allow this but I'm not too sure. Thanks for the help!
One way is to keep a field for uid along with the name, email and profileImageURI fields.
let rootRef = Database.database().reference()
guard let uid = rootRef.child("users").childByAutoId().key
Now, send the uid as a field while saving the data to firebase.
While retrieving the data you can map the data as follows :
let query = rootRef.child("users").queryOrdered(byChild: "users")
query.observe(.value) { (snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let value = child.value as? NSDictionary {
// declaring a user in class User() which was made with strings(name, email, etc.)
var dict = [String:String]()
let user = User()
let name = value["name"] as? String ?? "name not found"
// making the string of it go into the user.name
user.name = name
user.uid = value["uid"]
dict[name] = "\(uid)"
}
}

Firebase: Very Slow data show on Label text

I'm trying to observe information from my firebase database and store it in a dictionary, the problem is when I try to show these data on a label it takes a lot of time about 30 seconds, can you solve it please.
#objc func fetchUser() {
let user = Auth.auth().currentUser
if let user = user {
let uid = user.uid
let email = user.email
ref?.child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String : AnyObject] {
print(dictionary)
self.disName.text! = dictionary["DisplayName"] as! String
}
})
disUID.text = uid
disEmail.text = email
}
}

Load data from firebase to a label?

I have data in firebase that I would like to load into a UILabel with Swift.
My data structure looks like:
like-1bf89addclose
artists
-LP6zVO8iekRMMOWe7nm
artistGenre: pop
artistName: postmalone
id: 920930
And my swift code looks like:
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
refHandle = ref.observe(FIRDataEventType.value, with: {(snapshot) in
let dataDict = snapshot.value as! [String: AnyObject]
print(dataDict)
})
ref.child("artists").observeSingleEventOfType(.value, with: {(snapshot) in
let artist = snapshot.value!["artistName"] as! String
let genre = snapshot.value!["artistGenre"] as! String
self.artistlLabel.text = artist
self.genreLabel.text = genre
})
}
where's my mistake? I've tried searching online, but most examples only explain how to put input into tableviews, which has a different code I tried to understand and restructure but couldn't. I know there has to be something wrong with my ref but I can't figure it out.
I'm following a youtube tutorial and this works:
let userID: String = (FIRAuth.auth()?.currentUser?.uid)!
ref.child("Users").child(userID).observeSingleEventOfType(.value, with: {(snapshot) in
let email = snapshot.value!["Email"] as! String
let password = snapshot.value!["Password"] as! String
self.emailLabel.text = email
self.passwordLabel.text = password
})
**issue with this code is I don't need that authentication part (no users have to log in on my app, they're just inputing info in).
You're missing the -LP6zVO8iekRMMOWe7nm level in your reference. Try this:
ref.child("artists/-LP6zVO8iekRMMOWe7nm").observeSingleEventOfType(.value, with: {(snapshot) in
let artist = snapshot.value!["artistName"] as! String
let genre = snapshot.value!["artistGenre"] as! String
print("\(artist) \(genre)")
self.artistlLabel.text = artist
self.genreLabel.text = genre
})
If you want to load all artists, you can load /artists and then loop over the results:
ref.child("artists/-LP6zVO8iekRMMOWe7nm").observeSingleEventOfType(.value, with: {(snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
let artist = child.value!["artistName"] as! String
let genre = child.value!["artistGenre"] as! String
print("\(artist) \(genre)")
}
})