fnisi
fnisi

Reputation: 1223

Swift - Using a closure inside a repeat loop

I am trying to implement a user registration system and I need to know whether a user id (generated randomly) has already been assigned to another user or not. To do so, I connect my Firebase database and use the observer() method to check to availability of the generated id.

However, since the Firebase database query runs asynchronously and I can only know the result once the query returns, I am not able to use the correct return value from within the calling method.

My approach here is

repeat {
  id = generateUniqueId()
  check availability
} while (id is not unique)

The implementation I have is

var id:String
var test = true
repeat {
    id = generateId()
    ref.child("\(databaseReferenceName)").observe(.value) { (snapshot) in
        test = snapshot.hasChild("\(id)")
    }
} while (test == true)

This loop keeps running even though the test variable is set to false by the hasChild() method.

How can I change the code so that I would be able to capture the right value of the test variable?

I am using Swift 4.1

Thanks

Upvotes: 0

Views: 920

Answers (2)

Shehata Gamal
Shehata Gamal

Reputation: 100503

Since the process is asynchronous the loop will run until hit the first test = false , but i think you need this recursive way until find an available id

func checkID() {

       id = generateId()
       ref.child("\(databaseReferenceName)").observeSingleEvent(.value) { (snapshot) in
         let test = snapshot.hasChild("\(id)")

         if test {
           print("id exists")
           checkID() // check another one
         }
         else {
          print("this is the one \(id)")
         }
       }

}

another thing is that it should be observeSingleEvent instead of observe

Upvotes: 0

Duncan C
Duncan C

Reputation: 131418

You don't say, but I'm assuming the observe() function you're using is asynchronous, and will return before the work is done. As PaulW11 says, you need to trigger the next round in the completion handler:

func observeChildren() {
    var id:String
        id = generateId()
        ref.child("\(databaseReferenceName)").observe(.value) { (snapshot) in
            if snapshot.hasChild("\(id)") {
              observeChildren() //recursively call observeChildren again.
        }
}

Upvotes: 1

Related Questions