In my main VC I look for changes in my FB database like this:
ref.child(\"posts\").observe(.childChanged, with: { (snapshot) in
.......
})
First I would like to remind you about the singleton design patter : In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.
So the first thing you need to do is to create a call that contains as a parameters the data you get from firebase, I have did the following to get the following in order to get the user data when he logged in into my app and then use these data in every part of my application (I don't have any intention to pass the data between VC this is absolutely the wrong approach ) my user class is like this :
import Foundation
class User {
static let sharedInstance = User()
var uid: String!
var username: String!
var firstname: String!
var lastname: String!
var profilePictureData: Data!
var email: String!
}
after that I have created another class FirebaseUserManager (you can do this in your view controller but it's always an appreciated idea to separate your view your controller and your model in order to make any future update easy for you or for other developer ) So my firebaseUserManager class contains something like this
import Foundation
import Firebase
import FirebaseStorage
protocol FirebaseSignInUserManagerDelegate: class {
func signInSuccessForUser(_ user: FIRUser)
func signInUserFailedWithError(_ description: String)
}
class FirebaseUserManager {
weak var firebaseSignInUserManagerDelegate: FirebaseSignInUserManagerDelegate!
func signInWith(_ mail: String, password: String) {
FIRAuth.auth()?.signIn(withEmail: mail, password: password) { (user, error) in
if let error = error {
self.firebaseSignInUserManagerDelegate.signInUserFailedWithError(error.localizedDescription)
return
}
self.fechProfileInformation(user!)
}
}
func fechProfileInformation(_ user: FIRUser) {
var ref: FIRDatabaseReference!
ref = FIRDatabase.database().reference()
let currentUid = user.uid
ref.child("users").queryOrderedByKey().queryEqual(toValue: currentUid).observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() {
let dict = snapshot.value! as! NSDictionary
let currentUserData = dict[currentUid] as! NSDictionary
let singletonUser = User.sharedInstance
singletonUser.uid = currentUid
singletonUser.email = currentUserData["email"] as! String
singletonUser.firstname = currentUserData["firstname"] as! String
singletonUser.lastname = currentUserData["lastname"] as! String
singletonUser.username = currentUserData["username"] as! String
let storage = FIRStorage.storage()
let storageref = storage.reference(forURL: "gs://versus-a107c.appspot.com")
let imageref = storageref.child("images")
let userid : String = (user.uid)
let spaceref = imageref.child("\(userid).jpg")
spaceref.data(withMaxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
print(error.localizedDescription)
} else {
singletonUser.profilePictureData = data!
print(user)
self.firebaseSignInUserManagerDelegate.signInSuccessForUser(user)
}
}
}
})
}
}
so basically this class contains some protocols that we would implements and two functions that manager the firebase signIn and fechProfileInformation , that will get the user information
than in my login View controller I did the following : 1 implement the protocol
class LoginViewController: UIViewController, FirebaseSignInUserManagerDelegate
2 in the login button I did the following
@IBAction func loginAction(_ sender: UIButton) {
guard let email = emailTextField.text, let password = passwordTextField.text else { return }
let firebaseUserManager = FirebaseUserManager()
firebaseUserManager.firebaseSignInUserManagerDelegate = self
firebaseUserManager.signInWith(email, password: password)
}
3 implement the protocol method : func signInSuccessForUser(_ user: FIRUser) {
// Do something example navigate to the Main Menu
}
func signInUserFailedWithError(_ description: String) {
// Do something : example alert the user
}
So right now when the user click on the sign in button there is an object created which contains the user data save on firebase database
now comes the funny part (the answer of your question : how to get the user data in every where in the app)
in every part of my app I could make
print(User.sharedInstance.uid) or print(User.sharedInstance. username)
and I get the value that I want to.
PS : In order to use the singleton appropriately you need to make sure that you call an object when it's instantiated.