问题
I first attempted to instantiate each user in the database like so:
emails : {
email: "jerry@gmail.com" {
uid: "x"
}
}
I quickly found out that I can't store an email because it has an @
and .
. I was originally going to do an user look up like so:
func userLookUpByEmail (email: String) -> String {
var userID: String = "nil"
ref.queryOrderedByChild("emails").queryEqualToValue(email).observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
if snapshot.value != nil {
print(snapshot.value)
userID = snapshot.value as! String
}
else {
print ("user not found")
userID = "nil"
}
})
return userID
}
However, I'm realizing that won't work. What is an effective way to receive an UID from providing an email?
回答1:
Answering your question, since you can't have the email as the child key you can do the other way, setting the uid as the key and the email as the child.
emails : {
uid: {
email: "jerry@gmail.com"
}
}
And then your code will change a little bit.
func userLookUpByEmail (email: String, completionHandler: (result: String) -> Void) {
var userID: String = "nil"
ref.child("emails").queryOrderedByChild("email").queryEqualToValue(email).observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
if snapshot.value != nil {
print(snapshot.key)
userID = snapshot.key as! String
}
else {
print ("user not found")
userID = "nil"
}
completionHandler(userID)
})
}
Calling userLookUpByEmail
:
userLookUpByEmail(email) {
(result: String) in
print("\(result)")
}
On the other hand I'm wondering why do you have an emails
branch in your database since you could have an users
branch (if you don't have yet) and store any user data there, including the email. This would make your data structure much more clean and reliable. Again, I'm wondering here since I don't exactly know your needs.
users : {
uid: {
email: "jerry@gmail.com",
name: "Jerry Maguire",
...
}
}
回答2:
First of all, you are correct that you cannot store certain characters in the database. According to the Firebase docs, (https://firebase.google.com/docs/database/ios/structure-data)
If you create your own keys, they must be UTF-8 encoded, can be a maximum of 768 bytes, and cannot contain ., $, #, [, ], /, or ASCII control characters 0-31 or 127.
As you can see, however, the "@" symbol is not one of them. As for the dot, you can have a function that replaces the dot with another character. For example, "•". Here is an example:
func createNewEmail(oldEmail: String) -> String{
return oldEmail.componentsSeparatedByString(".").joinWithSeparator("•")
}
What that does is it splits the email into an array of "email@example" and "com". Then, it re-joins them with the new character, creating "email@example•com"
If you ever needed the old email, you could just do the same thing in reverse.
func getOldEmail(newEmail: String) -> String{
return newEmail.componentsSeparatedByString("•").joinWithSeparator(".")
}
You could then format your tree like this
emails:
email@example•com: UID123456789
Finally, for your original question, the function could be written like this
func userLookUpByEmail (email: String) -> String {
let newEmail = createNewEmail(email)
var userID: String = "nil"
ref.child("emails").child(newEmail).observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
if snapshot.value != nil {
print(snapshot.value)
userID = snapshot.value as! String
}
else {
print ("user not found")
userID = "nil"
}
})
return userID
}
However, it is possible that you will get "nil" every time. This is because observeSingleEventOfType is a closure. This means that it runs in the background of your app. Because of this, userID might be returned before it gets changed inside the closure. Instead of returning userID, you might want to run any code based on userID inside of the closure. For example, instead of doing this:
func userLookUpByEmail (email: String) -> String {
let newEmail = createNewEmail(email)
var userID: String = "nil"
ref.child("emails").child(newEmail).observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
if snapshot.value != nil {
print(snapshot.value)
userID = snapshot.value as! String
}
else {
print ("user not found")
userID = "nil"
}
})
return userID
}
doSomethingWith(lookUserUpByEmail(email@example.com))
You could do this:
func userLookUpByEmail (email: String){
let newEmail = createNewEmail(email)
var userID: String = "nil"
ref.child("emails").child(newEmail).observeSingleEventOfType(.ChildAdded, withBlock: { snapshot in
if snapshot.value != nil {
print(snapshot.value)
userID = snapshot.value as! String
doSomethingWith(userID)
}
else {
print ("user not found")
userID = "nil"
doSomethingWith(userID)
}
})
}
来源:https://stackoverflow.com/questions/38040648/finding-an-uid-by-email-in-firebase