简体   繁体   中英

Cannot check for unique username (Firebase)

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?

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. :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM