-2

I'm trying to return a name after getting it on Firestore, but for some reason it's not working.

Here's my code:

func getName() -> String {

        var name = ""

        db.collection("users").whereField("email", isEqualTo: user.email!).getDocuments { (snapshot, error) in

            if error != nil {

                print(error!)

            } else {

                for document in (snapshot?.documents)! {

                    name = document.data()["name"] as! String
                    // if I add `print(name) here, it works.`
                }
            }
        }
        return name
    }

But it returns an empty string :/ I want to return the actual name. How do I fix this?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Richard Reis
  • 219
  • 2
  • 10
  • 1
    Data is loaded from Firestore asynchronously, and your code continues to run while the data is being loaded. By the time your `return name` runs, the `name = document.data()["name"] as! String` hasn't run yet. I recommend you set some breakpoints and run the code in the debugger to verify this. There is no way to "solve" this and make the loading synchronous, as that would block your users from doing anything with the app. So instead you will need to put any code that needs the name **into** the callback/closure or call it from there. – Frank van Puffelen Mar 16 '19 at 14:03
  • For examples of this, see https://stackoverflow.com/a/53562898, https://stackoverflow.com/a/50460542, https://stackoverflow.com/a/51769180 and https://stackoverflow.com/a/41209941 – Frank van Puffelen Mar 16 '19 at 14:04
  • Possible duplicate of [In swift, how to make function to return querysnapshot from Firebase?](https://stackoverflow.com/questions/50458752/in-swift-how-to-make-function-to-return-querysnapshot-from-firebase) – Frank van Puffelen Mar 16 '19 at 14:07
  • Urgh. I was trying to put use this function as its own separate Model. Sounds like it won't work. Thanks for the info! – Richard Reis Mar 17 '19 at 00:53

1 Answers1

1

getDocuments is an asynchronous function. This means the name variable doesn't wait for the function to complete before continue executing. If you want to return the returned name from the document, you can take a look at the following code:

 func getName(_ completion: (String) -> ()) {
    db.collection("users").whereField("email", isEqualTo: user.email!).getDocuments { (snapshot, error) in
        if error != nil {
            print(error!)
        } else {
            for document in (snapshot?.documents)! {
                name = document.data()["name"] as! String
                completion(name)
            }
        }
    }
}

getName { name in
    print(name)
}
KeroppiMomo
  • 564
  • 6
  • 18