Reputation: 217
I searched for this question, but none of them had an answer that worked for me.
I want to make it so when a user registers an account, it checks to see if the username they have entered already exists, before creating the account. I have tried using querying in firebase, but I just can't seem to get it to work.
Here is an image of what my firebase data looks like: My firebase data tree
How would I use query to find the string for the key "username"?
Upvotes: 7
Views: 2135
Reputation: 3272
I do this next way:
The function of register:
@IBAction func signUpButtonTapped(_ sender: Any) {
User.getItemByLogin(for: userLogin.text!,
completion: { userItem in
if userItem == nil {
self.createAndLogin()
} else {
self.showAlertThatLoginAlreadyExists()
}
})
}
private func createAndLogin() {
FIRAuth.auth()!.createUser(withEmail: userEmail.text!,
password: userPassword.text!) { user, error in
if error == nil {
// log in
FIRAuth.auth()!.signIn(withEmail: self.userEmail.text!,
password: self.userPassword.text!,
completion: { result in
// create new user in database, not in FIRAuth
User.create(with: self.userLogin.text!)
self.performSegue(withIdentifier: "fromRegistrationToTabBar", sender: self)
})
} else {
print("\(String(describing: error?.localizedDescription))")
}
}
private func showAlertThatLoginAlreadyExists() {
let alert = UIAlertController(title: "Registration failed!",
message: "Login already exists.",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
}
My User class function. It's API like class:
static func getItemByLogin(for userLogin: String,
completion: @escaping (_ userItem: UserItem?) -> Void) {
refToUsersNode.observeSingleEvent(of: .value, with: { snapshot in
for user in snapshot.children {
let snapshotValue = (user as! FIRDataSnapshot).value as! [String: AnyObject]
let login = snapshotValue["login"] as! String // getting login of user
if login == userLogin {
let userItem = UserItem(snapshot: user as! FIRDataSnapshot)
completion(userItem)
return
}
}
completion(nil) // haven't founded user
})
}
In your way you should swap login
with username
.
Hope it helps
Upvotes: 0
Reputation: 72410
You can go like this, make one function with completion block to check username is already exist in your Firebase DB and create new user on the basis of it
func checkUserNameAlreadyExist(newUserName: String, completion: @escaping(Bool) -> Void) {
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrdered(byChild: "username").queryEqual(toValue: newUserName)
.observeSingleEvent(of: .value, with: {(snapshot: FIRDataSnapshot) in
if snapshot.exists() {
completion(true)
}
else {
completion(false)
}
})
}
Now simply call this function when you create new user:
self.checkUserNameAlreadyExist(newUserName: "Johnson") { isExist in
if isExist {
print("Username exist")
}
else {
print("create new user")
}
}
Upvotes: 9
Reputation: 8574
This is how I do it:
var text = "Your username"
let dbRef = FIRDatabase.database().reference().child("users")
dbRef.queryOrdered(byChild: "name").queryEqual(toValue: text).observeSingleEvent(of: .value, with: { snapshot in
if !snapshot.exists() {
// Name doesn't exist
}
if let data = snapshot.value as? [String: [String: String]] {
// it should exist if it reaches here
}
})
Make sure in your database rules to index the "users" node on "name" for performance optimization.
Upvotes: 3