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

在我的主要VC中,我查找FB数据库中的更改,如下所示:

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

从这个VC我可以进入VC2,这是设置为“现在modally”在我的segue。

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

那么有什么办法可以将数据从VC1发送到VC2,一旦节点已经更新,或者我必须在VC2中设置一个新的.observe()函数?

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

因此,您需要做的第一件事就是创build一个调用,其中包含从Firebase获取的数据作为参数,我已经完成了以下操作,以便在login到我的应用程序时获取用户数据,然后在我的应用程序的每个部分使用这些数据(我不打算在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! } 

之后,我已经创build了另一个类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) } } } }) } } 

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

比在我的login视图控制器我做了以下:1实施协议

 class LoginViewController: UIViewController, FirebaseSignInUserManagerDelegate 

2在loginbutton我做了以下

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

所以现在当用户点击loginbutton时,会创build一个包含用户数据保存在firebase数据库上的对象

现在来了有趣的部分(你的问题的答案:如何获得应用程序中的每个地方的用户数据)

在我的应用程序的每一个部分,我可以做

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

我得到了我想要的价值。

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