0

I have a function that has a function within it in terms of a call to a firebase database.

The internal function sets the value of a variable from the wrapper function, but my output does not register this. When debugging it looks like this happens in reverse order. I'm new to swift and firebase so i'm just trying to get my head round this.

This is my function and output.

func checkIfUsernameExists(inUsername: String) -> String{
    var aString = "false"
    let ref = FIRDatabase.database().reference()

    ref.child("-KohvyrIikykRsOP0XCx").observeSingleEvent(of: .value , with: {(snapshot) in
        if snapshot.hasChild(self.username.text!){
            print ("*** username already exists")
            aString = "true"
        }
    })

    print ("*** value of aString is: ", aString)
    return aString
}

output is:

*** value of aString is:  false
*** username already exists

Edit:

I phrased my question poorly i think.

What i meant to ask was how can i get the call back from firebase before processing the information its collected. I've bounced round SO and lots of blogs all pointing to Async, GCD and Completion handlers. None of which seemed to work or were easy enough for noob to get their head round.

Needless to say i've found my answer here.

Firebase Swift 3 Completion handler Bool

This is what i used:

func checkIfUsernameExists(userid: String, completionHandler: @escaping ((_ exist : Bool) -> Void)) {


        let ref = FIRDatabase.database().reference()
        ref.child("-KohvyrIikykRsOP0XCx").observeSingleEvent(of: .value , with: {(snapshot) in
            if snapshot.hasChild(self.username.text!){
                self.usernameCheck = "true"
                completionHandler(true)
                }

             else {
                self.usernameCheck = "false"
                completionHandler(true)
                }
        })
}
VynlJunkie
  • 1,953
  • 22
  • 26
  • 4
    Do some research on asynchronous method calls. – rmaddy Jul 16 '17 at 22:04
  • I can find this blog https://medium.com/@wilson.balderrama/how-to-make-a-async-calls-in-serial-in-swift-3-1debc21ff3c4 and something called async but i'm lost on both. can yo link and example ? – VynlJunkie Jul 16 '17 at 22:36
  • Possible duplicate of [Returning method object from inside block](https://stackoverflow.com/questions/22267865/returning-method-object-from-inside-block) – jscs Jul 16 '17 at 23:18
  • This is very duplicated question, but the short if it is; when you are working with asynchronous functions, the order that function occurs depends on how long it takes the data to get back to it. i.e. the print function will occur LONG before the Firebase closure. – Jay Jul 18 '17 at 18:11
  • 2
    Possible duplicate of [Access Firebase variable outside Closure](https://stackoverflow.com/questions/43823808/access-firebase-variable-outside-closure) – Jay Jul 18 '17 at 18:12

1 Answers1

0

It seems like that you are trying to get a value from firebase database. As you may know. data in your firebase database is stored remotely. This means that you need a relatively large amount of time to et your data, when compared with getting data from the disk.

Since it takes so long, the designers of the firebase API thought "Instead of making the UI wait and become unresponsive, we should fetch the data asynchronously. This way, the UI won't freeze."

In your code, this block of code:

if snapshot.hasChild(self.username.text!){
    print ("*** username already exists")
    aString = "true"
}

will be executed after it has fetched the data, which is some time later. Since the operation is done asynchronously, the rest of the function will continue to be executed, namely this part:

print ("*** value of aString is: ", aString)
return aString

And at this stage the closure hasn't been finished executing yet, aString is false.

This might sound counter intuitive, but think about it this way, you are calling a method here - observeSingleEvent. The code in the closure is meant to be a parameter. You are just telling the method to "Run this when you're done fetching the data". The data is fetched asynchronously, so the code after that executes first.

Sweeper
  • 213,210
  • 22
  • 193
  • 313