Reputation: 476
I am trying to check that a user-entered username is unique and does not match any that are currently in the database. I have found lots of similar questions on Stackoverflow about this, but none of them seem to work for me. Below is my current data structure:
users
-C3M483C28M34C29834C (uid)
• username: "myUsername"
I am currently using something along the lines of:
let ref = FIRDatabase.database().reference()
var usernameTaken = false
ref.child("users").queryOrderedByChild("username").queryEqualToValue(username.text?.uppercaseString).observeSingleEventOfType(.Value, withBlock: { snapshot in
if snapshot.exists(){
usernameTaken = true
}else{
usernameTaken = false
}
}) { error in
print(error.localizedDescription)
}
if usernameTaken == false{
//do stuff with unique username
}
This works great, and the snapshot is received. However, when I try to check if the data exists(), is always show it as false. Any recommendations on restructuring the code?
Upvotes: 0
Views: 410
Reputation: 598847
That will not work. Loading data from the Firebase database takes time and happens (like pretty much all of modern web programming) asynchronously. That means that your main code continues while the data is being loaded. And then when the data is available, your callback/withBlock gets invoked. You can most easily see this by adding some logging to your code:
print("Before attaching observer")
ref.child("users")
.queryOrderedByChild("username")
.queryEqualToValue(username.text?.uppercaseString)
.observeSingleEventOfType(.Value, withBlock: { snapshot in
print("In observer block")
})
print("After attaching observer")
The output of this will be:
Before attaching observer
After attaching observer
In observer block
That's probably not the order you expected. As said the code continues after the query part and your block is invoked later, potentially much later.
The solution is to reframe your way of thinking. Right now your code is "first do abc, then do xyz". If you change it to "when abc happens, do xyz with it", you will suddenly have fewer problems.
ref.child("users")
.queryOrderedByChild("username")
.queryEqualToValue(username.text?.uppercaseString)
.observeSingleEventOfType(.Value, withBlock: { snapshot in
if !snapshot.exists(){
//do stuff with unique username
}
}) { error in
print(error.localizedDescription)
}
This is often known as a "reactive programming style" or "event driven programming". So if you see those terms: you've now mastered them. :-)
Upvotes: 2