I made a function that connects to firebase, goes to a specific path and then gives me the value. When I print(snapshot.value), it gives me the value I need. When I call the function, userProfile is empty. I need userProfile to return the snapshot String.
func getUserData(uid: String) -> String{
var _REF_USERNAME = FIRDatabase.database().reference().child("users").child(uid).child("profile").child("username")
var userProfile = String()
_REF_USERNAME.observe(.value, with: {(snapshot) in
print("SNAP: \(snapshot.value)")
userProfile = snapshot.value as! String
})
print(userProfile)
return userProfile
}
Swift 3
You are calling userProfile outside of the callback in observe, so it'll be executed before the observe functions completes asynchronously. Callbacks are difficult to understand at first, but the general idea is that your code does not run sequentially from top to down, and there are some parts of the code that are run asynchronously in a background thread.
To get access to userProfile, you have to pass in a callback function just like that:
func observeUserProfile(completed: @escaping (_ userProfile: String?) -> ()) -> (FIRDatabaseReference, FIRDatabaseHandle) {
let ref = _REF_USERNAME
let handle = ref.observe(.value, with: {(snapshot) in
if !snapshot.exists() { // First check if userProfile exists to be safe
completed(nil)
return
}
userProfile = snapshot.value as! String
// Return userProfile here in the callback
completed(userProfile)
})
// Good practice to return ref and handle to remove the handle later and save memory
return ref, handle
And you call this observe code outside while passing in the callback function like that:
let ref, handle = observeUserProfile(completed: { (userProfile) in
// Get access to userProfile here
userProfile
}
And when you're done with this observer, stop it from observing to save memory by doing the following:
ref.removeObserver(withHandle: handle)