在两个视图控制器之间同步数据,以避免再次创建相同的观察者

时间:2017-04-19 13:43:24

标签: ios swift firebase firebase-realtime-database

在我的主VC中,我在这样查找FB数据库中的更改:

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

从这个VC我可以输入VC2,它在我的segue中设置为“模态存在”。

现在我想知道我是否可以将实时FB数据从VC1传递到VC2?我知道我可以使用segue.identifier并在我转到下一个VC时传递数据,但这只是发送的一次。或者我应该设置一个委托来从vc1获取数据到vc2?

一旦节点更新,我是否可以将数据从VC1发送到VC2?或者我必须在VC2中设置新的.observe()功能吗?

1 个答案:

答案 0 :(得分:2)

首先,我想提醒一下单身设计模式: 在软件工程中,单例模式是一种软件设计模式,它将类的实例化限制为一个对象。当在整个系统中协调操作只需要一个对象时,这非常有用。

所以你需要做的第一件事就是创建一个调用,其中包含从firebase获取的数据作为参数,我已经做了以下操作来获取以下内容,以便在登录到我的用户数据时获取用户数据app然后在我的应用程序的每个部分使用这些数据(我没有任何意图在VC之间传递数据这绝对是错误的方法) 我的用户类是这样的:

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!
}

之后我创建了另一个类FirebaseUserManager(您可以在视图控制器中执行此操作,但是为了使您或其他开发人员可以轻松地对您的控制器和模型进行任何更新,我们总是非常欣赏这一点。) 所以我的firebaseUserManager类包含类似这样的东西

    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)
                        }
                    }
                }
            })
        }
    }

所以基本上这个类包含一些我们要实现的协议和两个管理firebase signIn和fechProfileInformation的函数,它们将获取用户信息

比在我的登录视图控制器中我做了以下操作: 1实现协议

class LoginViewController: UIViewController, FirebaseSignInUserManagerDelegate
登录按钮中的

2我做了以下

 @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实现协议方法:   func signInSuccessForUser(_ user:FIRUser){

   // Do something example navigate to the Main Menu 
}

func signInUserFailedWithError(_ description: String) {
    // Do something : example alert the user
}

所以现在当用户点击登录按钮时,会创建一个对象,其中包含firebase数据库中的用户数据保存

现在出现了一个有趣的部分(你的问题的答案:如何在应用程序的每个位置获取用户数据)

在我的应用程序的每个部分我都可以

print(User.sharedInstance.uid) or print(User.sharedInstance. username)

我得到了我想要的价值。

PS:为了适当地使用单例,你需要确保在实例化时调用一个对象。