I have a user object that I am getting its values from firebase and I want to pass this object basically in all of my other view controllers. I am using storyboard and I looked up how to do this and I found out that I can override the prepare method, I wasn’t successful with that as I did not know how to call the method or if it was ever called, it just didn’t work. Then I found that you can just assign a vc to another view controller and pass data like that but I hit an issue:
In HomeViewController, I have this method that gets data from firebase and assign it to user:
extension HomeViewController {
public func AssignValueToUserObject() {
guard let uid = Auth.auth().currentUser?.uid else {
print("Could not get user id")
return
}
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { [self] snapshot in
if let dictionary = snapshot.value as? [String: AnyObject] {
user.first_name = dictionary["first_name"] as? String
user.last_name = dictionary["last_name"] as? String
user.email = dictionary["email"] as? String
user.profile_picture = dictionary["profile_picture"] as? String
}
}, withCancel: nil)
} // End AssignValueToUserObject Method
} // End extension
And this is what I have in HomeViewController to copy that user object to my ProfileViewController:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
title = "Home"
checkIfUserIsLoggedIn()
copyData()
}
func checkIfUserIsLoggedIn() {
// Check if user is logged in
if Auth.auth().currentUser == nil {
// User is not logged in, send user to login screen
let loginVC = storyboard?.instantiateViewController(identifier: "login")
loginVC?.modalPresentationStyle = .fullScreen
present(loginVC!, animated: false)
}
// User is logged in, fetch their info
AssignValueToUserObject()
} // End checkIfUserIsLoggedIn method
// Copy user from Home to Profile
func copyData() {
let vc = storyboard?.instantiateViewController(identifier: "profile") as? ProfileViewController
vc?.user = user
}
After debugging, I found the BIG problem, which is that the copy method gets called BEFORE the values gets assigned to user in the AssignValueToUserObject method, which to me makes absolutely no sense.
I call the assign method before the copy method so how does that work? After some research, I figured out it has something to do with completion handling but I just don’t get it.
2
Answers
As mentioned in the comments, with asynchronous functions, you can’t expect a return value right away. One common way to handle this is by using a callback function or completion handler.
I’m including a very basic example of this. Note that I’m not doing any error handling right now — you’d want to build it out to be more robust, but this at least gets the concept:
Update, showing a way to use a singleton to monitor a user value in different view controllers:
Try this