Display the name of a user using Firebase - ios

What I want to do is to make a top header in the app with the name of the user displayed in a label. I know everything to do this except how to reference their name. To give more clarity this is what I want (even though this doesn't work in the newest version of xcode);
let userName = Auth.auth().currentUser.name
// so this is the string of the users name
I know this seems really simple and there is probably an easy way to do it that I'm not sure of. Thanks for the help!

This is how I access my firebase realtime database and read from it:
let ref = Database.database().reference()
ref.child("Username").observeSingleEvent(of: .value) {(snapshot:DataSnapshot) in
let userName = snapshot.value as? String
Print(userName)
}
Instead of where I put "Username", you can replace this with the name of the node under which the value you want to output is stored. And if this node is the child node of another, you can continue to add .child("XXX") to the line of code.
e.g.
ref.child("Account").child("Username").observeSingleEvent(of: .value) {(snapshot:DataSnapshot) in

It's tucked away a little, in providerData, which is an instance of UserInfo...
let user = Auth.auth().currentUser
let userName = user.providerData.displayName

Related

Problem with logic when it comes to storing dictionary values in firestore

I am trying to re-create the instagram follower and following functionality but there seems to be an error in logic. There is no error in code. What I am doing right now when the "follow" button is pressed, is to create a collection called "user-following", add the "current UID" as "document ID" and then store the following target users data as [targetuid: 1]. At the same time, I create a collection called "user-followers", add the "Target UID" as "document ID" and then store the followers data as [currentuid:1]. The issue here is that it works when it comes to following just one user. When I try to follow another, the existing following user data gets overridden with the new user whom I just followed instead of appending the data.
Example: Assume currentUser is A, user1 = B, user2 = C
When I follow user1 and user2 my database in firestore should be reflected as:
user-following -> A -> [B:1,C:1]
user-followers -> B -> [A:1]
user-followers -> C -> [A:1]
The above translates to collection -> documentID -> dictionaryvalues
The problem is that I do not get the above result. Instead when I follow user2, the value of user1 gets overridden. So there is only one dictionary value stored.
I know that the problem lies somewhere in the way I am trying to create a field under the document ID. I know I can create a dictionary and append values but I think that's a lot of code for an otherwise simple solution.
func follow(){
guard let currentUid = Auth.auth().currentUser?.uid else
{return}
guard let uid = uid else {return}
self.isFollowed = true
// Add followed user to current user-following structure
Firestore.firestore().collection("user-
following").document(currentUid).setData([uid:1])
// Add current user to followed user-follower structure
Firestore.firestore().collection("user-
followers").document(uid).setData([currentUid:1])
}
Never mind. Realised that I had to use merge.
Firestore.firestore().collection("user-
following").document(currentUid).setData([uid:1], merge: true)

Swift Firebase database overwriting

I am making a real-time messenger using Firebase. Currently, whenever I press a button I want a new message to be appended to the channel with the index of the message, but currently, whenever I press the button a new message is created that overwrites the old message. I know that setValue is usually the issue, but I really cannot tell what I'm doing wrong. What the database looks like before I add my new message. This is what it looks like after I add a new message here, and then the code I am using to add to the database.
#IBAction func sendMessageTapped(_ sender: Any) {
if messageTextField.text == "" {
print("blank")
return
} else {
// First we will update the amount of messages that the channel has.
ref.child("channels").child(channelName!).setValue(["numberOfMessages" : numberOfMessages+1 ])
numberOfMessages += 1
// after we have updated the amount of messages we will try to create a new message.
ref.child("channels").child(channelName!).child("messages").child(String(numberOfMessages)).child("message").child("content").setValue(messageTextField.text)
ref.child("channels").child(channelName!).child("messages").child(String(numberOfMessages)).child("message").child("name").setValue("Buddy")
}
}
ok, Firebase is not a traditional table based database, is a DOCUMENT based database. At the very top you have a thing called a "collection" which is just a list of "document" things. In your case, you'd have several collection things to serve as channels: "General", "TopicQ", "InterstingStuff" etc, and within them each message as a document. No need to have a document, to then list the messages within it.
Second, you don't need indexes as you're using them, make the message id an attribute of the message, because firebase support querying by field, and even then is questionable because if you make each message a document, they will have their own auto generated id's if you want.
Third, in your code you're rewriting the whole document each time, this is why you lose your previous messages, so if you keep it, you need to add a merge option:
// Update one field, creating the document if it does not exist.
db.collection("cities").document("BJ").setData([ "capital": true ], merge: true)
you probably want to do something like this. This is what I did for my app, hope this helps someone. This rootRef.childByAutoId() generates a new entry with unique id. You can use this as reference for your case.
let rootRef = Database.database().reference(withPath: "channels")
let childRef = rootRef.childByAutoId()
let values = ["Type": self.textField.text!, "message": self.textView.text!] as? [String : Any]
childRef.updateChildValues(values)

How do I set the name a child in Firebase to user input from a text field?

Here's how I want my data tree to look in Firebase:
users:
--Travis:
------travisData:
--Stephanie:
------stephanieData:
My problem is that I can't seem to name a child using user input from a textfield.
Here's the code I have so far:
ref = Database.database().reference()
let username = String(emailTextField.text!)
//ref.child("users").setValue(["username": username])
ref.child("users").setValue(["\(username)": calendar])
The commented out line creates a child named "username" with the textfield.text as its content. But how can I create a child whose name is the textfield.text, with other data as its content? I've tried multiple combinations of using .child and .setValue, but everything keeps throwing me an error when I try to use the username variable instead of a plain string.
Here's the error I get:
Your problem is that Firebase doesn't accept the "." symbol in their user names. You would get the same problem even if you typed a string of letters with a "." such as "adfojnajsdnfjs.fjknasd" instead of "username".
I think you're looking for:
ref.child("users").child(username).setValue(calendar)
Although that depends on the value of calendar.
At the very least this should work:
ref.child("users").child(username).setValue(true)
And give you the following JSON:
"users": {
"Travis": true
}
To write a more complex structure, you can for example do:
ref.child("users").child(username).child("name").setValue(username)
Which results in:
"users": {
"Travis": {
name: "Travis"
}
}
As your require, I think this code will help you
ref.child("users").child("\(inputUsername)").updateChildValues(["travidDataKey": userData])
And
result image
users:
Travid2:
travidDataKey:"Travid Data"

Search Firebase Query with array of unique keys

I have my schema set as follows.
Now i want to send the a string chinohills7leavescafe101191514.19284 and want to check if there is any string in the Chino Hills or not.
I am confused to make any search query because i have not stored above string in fixed childKey
I know the schema should be like this but i cannot change the schema.
leaves-cafe
codes
Chino Hills
-Kw0ZtwrPjyNh1_HJrkf
codeValue: "chinohills7leavescafe101191514.19284"
You're looking for queryOrderedByValue. It works the same ways as queryOrderedByChild and allows you to use queryEqualToValue to achieve the result you need since you can't alter your current schema.
Here's an example
// warning: untested code - just illustrating queryOrderedByValue
let ref = Database.database().reference().child("leaves-cafe").child("codes").child("Chino Hills")
let queryRef = ref.queryOrderedByValue().queryEqual(toValue: "chinohills7leavescafe101191514.19284")
queryRef.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
print("value does exists")
} else {
print("value doesn't exist")
}
})
Your alternative option is to iterate over all nodes and check if the value exists manually as 3stud1ant3 suggested. However, note that this approach is both costy and a security risk. You would be downloading potentially a lot of data, and generally you shouldn't load unneeded data (especially if they're sensitive information, not sure if that's your case) on device; it's the equivalent of downloading all passwords off a database to check if the entered one matches a given user's.

databaseRef Firebase withoud childByAutoID()

Guten Tag,
i'm uploading some text to firebase through my iOS Application, but i can't find a code, where i can give the App User not a random ID, but maybe the email for the id to upload or Name. I hope you understand what i mean.
Current Code:
let logininit : [String : AnyObject] = ["text4" : text4!, "text5" : text5!, "text6" : text6!]
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Logins").childByAutoId().setValue(logininit)
Now i want to remove this childByAutoID, and set it to, how i said, email or name of the user.
Firebase Database
EDIT
Resolved this Problem: databaseRef.child("Logins").child(The Email That You Want Here).setValue(logininit)
I think I understood what you meant, but I don't see reasons for you to do that. Usually when you have a new entry on some entity, you usually gives it a unique ID (UUID). So, I think if you use child(The Email That You Want Here), should work as you want:
databaseRef.child("Logins").child(The Email That You Want Here).setValue(logininit)

Resources