-1

I am making an app in which I have to return a String representing the existence of a certain reference to my firebase realtime database (I am not using a Bool for other reasons). Despite executing the print commands directly above and below, when I print the function, the value of the String won't change and prints its default value "Unchanged".

My code:

func checkIfMovieHasAlreadyBeenShown(movieID: String) -> String {

    var hasItBeenSeen = "Unchanged"
    let uid  = Auth.auth().currentUser?.uid
    let ref = Database.database().reference()
    ref.child("Seen Movies").child(uid!).observeSingleEvent(of: .value, with: { (snapshot) in

        if snapshot.hasChild(movieID){
            print("The Result:")
            self.changeStringHasItBeenSeen(YNString: "yes")
            print("YES")
        }

        else {
            print("The Result:")
            self.changeStringHasItBeenSeen(YNString: "no")
            print("NO")
        }
    })

    return hasItBeenSeen
}

It is printed here:

print(checkIfMovieHasAlreadyBeenShown(movieID: "39"))
print(checkIfMovieHasAlreadyBeenShown(movieID: "38"))
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Bob Samuels
  • 53
  • 10
  • @Schemetrical's answer is indeed the problem: when your `return hasItBeenSeen` runs, the value hasn't been loaded yet. Also see: https://stackoverflow.com/questions/43854811/return-statement-error-using-firebase-in-swift, https://stackoverflow.com/questions/43823808/access-firebase-variable-outside-closure/43832208#43832208, https://stackoverflow.com/questions/41262793/swift-wait-for-firebase-to-load-before-return-a-function, https://stackoverflow.com/questions/42894472/swift-firebase-function-return – Frank van Puffelen Aug 06 '18 at 02:54

1 Answers1

3

observeSingleEvent is called in a closure. The return hasItBeenSeen line will not be affected by anything in the closure, as it will return first.

Imagine this: you tell your friend to go buy some apples. Before he has even left, you ask him for the price. Of course, he won't know, because he hasn't gone to buy the apples yet.

You need some way of performing something AFTER the closure has been called (or after the apples have been bought). Usually this can be done with a completion handler, where you pass a closure into your checkIfMovieHasAlreadyBeenShown function, such as, "do this AFTER you buy the apples".

Then you would call your function this way: checkIfMovieHasAlreadyBeenShown(movieID: "39", completion: { seen in print(seen) })

Schemetrical
  • 5,506
  • 2
  • 26
  • 43