I'm, developing a simple app to store users images. User authorized via Facebook, and the interact with app.
I stuck with retrieving data from current user.
In my firebase for now I have such structure:
I decided to get user data by uid.
So I initialized variable
let userID = FIRAuth.auth()?.currentUser?.uid
Then I retrieve an array of objects from my database
URL_BASE.child("profile").observeEventType(.Value, withBlock: { (snapshot) in
print (snapshot.value as! [String:AnyObject]!)
})
}
In my output I have this:
"-KJSKE4a2y-okl71vDSx": {
Interest = men;
gender = female;
name = girlsname1;
photo = "http://i.imgur.com/VAWlQ0S.gif";
surname = girlsurname1;
}, "-KJSKE4b8TlvxV-urHQo": {
Interest = men;
gender = female;
name = girlsname6;
photo = "http://media.tumblr.com/tumblr_lnb9aozmM71qbxrlp.gif";
surname = girlsurname6;
And so on
It is ok, but my goal is to print data of currently authorized user. I have an idea of sorting all objects by uid, but I think it is irrational. Hope there is simpler solution.
Authorized users stores in users database. profile database consist of user parameters I'm getting from Facebook.
let userID : String = (FIRAuth.auth()?.currentUser?.uid)!
print("Current user ID is" + userID)
self.dbRef?.child("profile").child(userID).observeSingleEvent(of: .value, with: {(snapshot) in
print(snapshot.value)
let userEmail = (snapshot.value as! NSDictionary)["addedByUser"] as! String
print(userEmail)
})
In Firebase, all users have a uid as you know. The uid should be used as the key for each user node in /users.
uid_0
gender: male
name: Leroy
uid_1
gender: female?
name: pat
This is a common design pattern in Firebase.
With that, you can simply get any user by their uid
let thisUserRef = usersRef.childByAppendingPath("the uid")
thisUserRef.observeSingleEventOfType(.Value... {
let gender = snapshot.value["gender"]
}
Related
I have this data structure and I can't extract the right value:
users
private
userID
birthday: "birthdayValue"
username: "nathan"
firstName: "Nathan"
etc...
I'm making a search feature in my app to search for users via their username through the firebase realtime database:
let reference = Database.database().reference()
if(searchText != ""){
reference.child("users").child("private").queryOrdered(byChild: "username").queryStarting(atValue: searchText).queryEnding(atValue: searchText + "\u{f8ff}").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.value is NSNull{
//handles errors
return
}
else{
if let user = snapshot.value as? NSDictionary {
for child in user{
print(child.key)
print(child.value)
}
}
else{
//null
}
}
})
at the moment the two print statements are printing these two results in the console every time I search:
wnszfmHilqNl6PG9khWtWkKUPtF3
{
birthday = 100;
dateCreated = "1579543450313.94";
description = nil;
email = "email#email.com";
firstName = Nathan;
instagramLink = nil;
lastLogin = "1579543450313.988";
lastName = Ellis;
profilePicURL = "url";
twitchLink = nil;
username = nathan;
youtubeLink = nil;
}
Which is expected, it prints the usersID (the key) and the value of the snapshot as a NSDictonary. I'm only interested in getting the username, nothing else. How would I extract the username out of this firebase snapshot so I can add their username as a string to an array for my search controller?
Obviously it needs to be dynamic as the userID will always be different.
Would I need to change my data model?
Your child.value seems to be a dictionary as well, so you can access it by:
if let valueDict = child.value as? [String: AnyObject] {
if let username = valueDict["username"] as? String {
// append username to results
print(username)
}
}
To print just the username, the smallest possible change is:
print(resultsLocalArray["username"])
This will fine, but will still retrieve the entire user node to the client, which uses more bandwidth than strictly needed.
If you find yourself frequently needing just the username of a user, or maybe even a list of username values across users, you might want to consider storing a node with just user names. So something like:
users
userID: "nathan"
But in your current setup you only retrieve the node for a single user, so I doubt the bandwidth savings are worth the additional complexity.
I am trying to access nested data values based on profile uid. with this One profile based on uid has multiple friends and friends have location and profile image (in profile) object.
I am using CodableFirebase and models for Friend,Profile,LastLocation. for main data list I use observeSingleEvent(of: .value and for all other nested data I need to use .observe(.childAdded .
Second thing How would I read all values based on profile uid and save them into an Array that I can then display in a TableView ?
I am not getting an idea how to do that please anyone help me.
Firebase Database:
zzV6DQSXUyUkPHgENDbZ9EjXVBj2
friends
FTgzbZ9uWBTkiZK9kqLZaAIhEDv1
conversationUid: "-L_w2yi8gh49GppDP3r5"
friendStatus: "STATUS_ACCEPTED"
notify: true
phoneNumber: "+055441503"
uid: "FTgzbZ9uWBTkiZK9kqLZaAIhEDv1"
HHCBYyP4KybcINgZaWVukR967l12
IcBfQKAnswQ7rivFuZsPvRUcsX43
LEZ2FUxS1WVaqSEHx5YqnpZ5Els1
YyFIm4hTorMFq4olpvHJI7e5e3a2
nkS2cjSvmLUEYEKsAVyErz9HkrJ2
lastLocation
batteryStatus: 27
latitude: 41.0220811
longitude: 29.0445012
timeStamp: 1571742057730
uid: "zzV6DQSXUyUkPHgENDbZ9EjXVBj2"
profile
fcmToken: "enMneewiGgg:APA91bHyA4HypWUYhxGTUTTcWch8ZJ_6UUW..."
name: “My Profile name”
phoneNumber: "+05588674"
picture: "profile/zzV6DQSXUyUkPHgENDbZ9EjXVBj2/a995c7f3-7..."
uid: "zzV6DQSXUyUkPHgENDbZ9EjXVBj2"
Code:
let ref = Database.database().reference()
ref.child("users").child("zzV6DQSXUyUkPHgENDbZ9EjXVBj2").observeSingleEvent(of: .value, with: { (snapshot) in
for userSnapshot in snapshot.children.allObjects as! [DataSnapshot] {
let friendsSnapshot = userSnapshot.childrenCount
do {
let frndList = try FirebaseDecoder().decode(Friend.self, from: friendsSnapshot)
self.AppData = [frndList]
print(frndList)
self.tableView.reloadData()
} catch let error {
print(error)
}
I have a ref named Following. Under that ref there are 2 different userIds who are following the same user. If the user they are both following wants to delete their account I want to delete them from the Following node. Multi location update doesn't seem correct to achieve this.
How can it be done?
User kk8qFOIw... is the user who is deleting their account. Once deleted their keys should be removed from the other user's nodes.
This is how you can do it :
First get all the nodes where your id = 1 , then run a multipath update and set them to empty.
let userId = "yourUserId"
self.ref.child("following").queryOrdered(byChild: userId).queryEqual(toValue: 1).observeSingleEvent(of: .value) { (snasphot) in
guard let value = snasphot.value as? [String : Any] else {return}
var multipathUpdate = [String:Any]()
value.keys.forEach({ (key) in
multipathUpdate["following/"+key+"/"+userId] = [:]
})
self.ref.updateChildValues(multipathUpdate, withCompletionBlock: { (err, ref) in
})
}
I am trying to store user posts in my firebase data like the following:
I have successfully stored each image in storage with the following code:
let storage = FIRStorage.storage()
let data = UIImagePNGRepresentation(postImage!)
// guard for user id
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
let photosRef = storage.reference().child("posts")
let imageName = NSUUID().uuidString
let photoRef = photosRef.child("\(uid)")
photoRef.child("\(imageName)").put(data!, metadata: nil){(metaData,error) in
if let error = error {
print("there was an error")
print(error.localizedDescription)
return
}else{
// store downloadURL
let downloadURL = metaData!.downloadURL()!.absoluteString
let values = ["uid": uid, "caption": caption, "download_url": downloadURL]
// store downloadURL at database
let databaseRef = FIRDatabase.database().reference()
// store values in posts/post_1 (post_1..post_2 etc)
}
}
However, I'm having trouble storing the downloadURL (values array) in my posts database because I can't figure out how to have an incremental value for post 1 post 2 post 3 etc etc
Is there a better way to store the posts in the posts database without needing incremental values?
Appreciate any help.
Thanks!
There are a number of ways to store incremental values - it all depends on how you want the values stored and how you will be retrieving and using them.
The general process is to create parent nodes using childByAutoId - Firebase generates the distinct node names for you.
let ref = rootNode.childByAutoid()
ref.setValue("my value")
This will result in nodes with a Firebase generated key
root_node
-Ynaosdokasodkpasd: "my Value"
That being said, it's hard to order them in a meaningful way, so you may want to add nodes that will enable you to specify the order
let ref = rootNode.childByAutoid()
let dict = ["text": "my value", timeStamp: "20161207131600"]
ref.setValue(dict)
which results in
-Ynaosdokasodkpasd
text: "my value"
timeStamp: "20161207131600"
you can then use the timeStamp to order your data in Firebase queries.
I am working on iOS application using swift, and I have the following data in firebase dashboard of the application
Users =
{
"07a5fa11-2a09-455b-92bf-a86dcd9d3e3e" =
{
Name = "Hissah";
Category = "Art & Designe";
City = "Riyadh";
Email = "H#him.fm";
ShortDescription = "";
};
"08e5443c-cdde-4fda-8733-8c4fce75dd34" =
{
Name = "Sara";
Category = "Cheefs";
City = "Dubai";
Email = "Sara#gmail.com";
ShortDescription = "best cake ever . ";
};
How can I retrieve the (Name) of the users whose (City) is "Riyadh" to a table view?
Thanks in advance.
Tossing this in the ring as it's a straightforward answer and addresses a dataSource that can be used to populate a tableView
let ref = Firebase(url:"https://your-app.firebaseio.com/users")
ref.queryOrderedByChild("City").queryEqualToValue("Riyadh")
.observeEventType(.Value, withBlock: { snapshot in
//iterate over all the values read in and add each name
// to an array
for child in snapshot.children {
let name = child.value["Name"] as! NSString
self.tableViewDataSourceArray.append(name)
}
//the tableView uses the tableViewDataSourceArray
// as it's dataSource
self.tableView.reloadData()
})
Edit: A follow up comment asked how to add the text to a NSTextView
ref.queryOrderedByChild("City").queryEqualToValue("Riyadh")
.observeEventType(.Value, withBlock: { snapshot in
//iterate over all the values and add them to a string
var s = String()
for child in snapshot.children {
let name = child.value["Name"] as! NSString
s += name + "\n" // the \n puts each name on a line
}
//add the string we just build to a textView
let attrString = NSAttributedString(string: s)
self.myTextView.textStorage?.appendAttributedString(attrString)
})
With your current node "Users" you would have to download all users and individually check to see which ones have the city "Riyadh". This would be a waste because you would be reading a lot of data you might not need.
If searching for users by city is a main feature of your app I would make another node "Cities" which would contain a list of cities. Each city node would then contain a list of all the users in that city and you could query that node. Then if you need more information on those users you know which specific people to look up in your "Users" node. You could then use this information however you see fit in your table view.
Cities:
{
"Riyadh":
{
"07a5fa11-2a09-455b-92bf-a86dcd9d3e3e":true
},
"Dubai":
{
"08e5443c-cdde-4fda-8733-8c4fce75dd34":true
}
},
Users:
{
"07a5fa11-2a09-455b-92bf-a86dcd9d3e3e":
{
Name: "Hissah";
Category: "Art & Designe";
City: "Riyadh";
Email: "H#him.fm";
ShortDescription: "";
};
"08e5443c-cdde-4fda-8733-8c4fce75dd34":
{
Name: "Sara";
Category: "Cheefs";
City: "Dubai";
Email: "Sara#gmail.com";
ShortDescription: "best cake ever . ";
};
Further reading here, where it talks about denormalizing data:
https://www.firebase.com/docs/web/guide/structuring-data.html