我正在使用Firebase开发iOS应用。我的根视图控制器是UITabBarController
。
上述TabBar中的所有控制器都需要侦听Firebase Firestore中的User
文档,但是在每个侦听器中创建侦听器似乎并不是最有效的方法。
我知道我可以像这样在CustomTabBarController
中创建侦听器:
import UIKit
import FirebaseFirestore
class CustomTabBarController: UITabBarController {
var userListener: ListenerRegistration?
var user: User? // User is a custom class
override func viewDidAppear(_ animated: Bool) {
let userID = UserDefaults.standard.value(forKey: "id") as! String
userListener = Firestore.firestore().document("users/\(userID)").addSnapshotListener { (document, error) in
if let document = document {
self.user = User(firebaseDocument: document)
} else {
// handle error!
}
}
}
override func viewDidDisappear(_ animated: Bool) {
if let listener = userListener {
listener.remove()
}
}
}
,然后从所有user
访问该ChildViewController
属性,如下所示:
class ChildViewController: UIViewController {
var user: User?
override func viewDidLoad() {
super.viewDidLoad()
let customTabBarController = tabBarController as! CustomTabBarController
self.user = customTabBarController.user
}
}
我发现这种方法存在两个问题:
user
中的ChildViewController
属性仅在viewDidLoad
方法中设置,因此不会更新。CustomTabBarController
是处理侦听器失败的地方。不同的ChildViewController
将有不同的处理方式。 问题:创建能够更新需要其结果的任何UIVIewController
的侦听器的我有哪些选择?我是在正确的道路上吗,或者我可以使用AppDelegate
甚至是Singleton来实现这一目标。
谢谢!
答案 0 :(得分:1)
在您当前的班级中,您可以使用以下方式访问所有vcs
self.viewControllers
并通过强制转换获得新的用户更新时应用所需的更新,或使用以下方法听用户
var ob:NSKeyValueObservation!
// in viewDidLoad
let tab = self.tabBarcontroller as! CustomTabBarController
ob = tab.observe(\.user, options: [.new]) { (tab, change) in
//
}
在每个孩子的内部,或者您可以使用NotificationCenter进行1-M观察,出于分离目的,请考虑一下用户
class Service {
static let shared = Service()
var userListener: ListenerRegistration?
var user: User? // User is a custom class
func listenToUpdates() {
let userID = UserDefaults.standard.value(forKey: "id") as! String
userListener = Firestore.firestore().document("users/\(userID)").addSnapshotListener { (document, error) in
if let document = document {
self.user = User(firebaseDocument: document)
} else {
// handle error!
}
}
}
}
然后
Service.shared.listenToUpdates()
答案 1 :(得分:0)
您可以创建一个服务类,该服务类将处理对Firestore
的查询。如果然后要将结果传递给视图控制器,只需调用闭包即可。您可以执行以下操作:
class FirestoreApiService {
func getFirebaseUser(withId id: String, then completion: @escaping ((Result<User>) -> Void)) {
Firestore.firestore().document("users/\(userID)").addSnapshotListener { (document, error) in
if let document = document {
completion(.success(User(firebaseDocument: document))
} else {
completion(.failure(error))
}
}
}
}
Result
仅是通用结果枚举:
enum Result<Value> {
case success(Value)
case failure(Error)
}
然后在您的ChildViewController
中调用方法:
let apiService = FirestoreApiService()
apiService.getFirebaseUser(withId: "12345") { result in
switch result {
case .success(let user):
//handle success
case .error(let error):
//handle error
}
}
请记住,这只是伪代码,未经测试。