Sync data between two viewcontrollers to avoid creating same observer again

前端 未结 1 1384
南方客
南方客 2021-01-21 10:44

In my main VC I look for changes in my FB database like this:

ref.child(\"posts\").observe(.childChanged, with: { (snapshot) in
  .......                
})
         


        
1条回答
  •  温柔的废话
    2021-01-21 11:25

    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.

    0 讨论(0)
提交回复
热议问题