Postscript. As I wrote, if you are a logged-in user, Observe (Listen) will run twice (because viewDidLoad of ViewController is called twice), so it will be strange, and it seems that Listen is correct to do with viewWillAppear. https://firebase.googleblog.com/2015/10/best-practices-for-ios-uiviewcontroller_6.html
However, it repeats Listen and remove every time in tab transition, so if you want to quit this, it seems that you need to avoid it by another method.
I will leave it for a while, but I will erase it or rewrite it later.
Implemented login using Firebase Auth in an app with a tab bar. Initial View is MyTabBarController. The first view of MyTabBarController as the home is the view controller.
If the user is not authenticated, LoginView/SignUpView is opened with PresentModally and closed with dissmiss when login is completed (I think that there is no extra parent or processing for the logged-in user).
MyTabBarController which is the initial view and viewDidLoad and viewDidAppear of its child view controller are called first. Even if you dissmiss after logging in, viewDidLoad, viewWillAppear, and viewDidAppear of the child view controller are not called. When I logged in there, I had to reload (initialize) MyTabBarController or its children.
After dismiss, I reloaded only the first child in viewDidAppear of MyTabBarController.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard let _ = Auth.auth().currentUser else {
self.presentWelcomeView()
return
}
self.viewControllers?.first?.loadView()
self.viewControllers?.first?.viewDidLoad()
}
MyTabBarController.swift
import UIKit
import FirebaseAuth
class MyTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard let _ = Auth.auth().currentUser else {
self.presentWelcomeView() //If you don't call it here, whose view is not in the window hierarchy!I get angry with the error (It seems that ViewDidLoad is only loaded but not generated)
return
}
// self.setViewControllers(self.viewControllers, animated: true) //This is no good
self.viewControllers?.first?.loadView()
self.viewControllers?.first?.viewDidLoad()
}
func presentWelcomeView() {
guard let controller = storyboard?.instantiateViewController(identifier: "WelcomeNavigation") else { return }
controller.modalPresentationStyle = .fullScreen
self.present(controller, animated: true, completion: nil)
}
}
ViewController.swift
import UIKit
import FirebaseAuth
import FirebaseFirestore
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
var posts: [Post] = []
var user: User!
let db = Firestore.firestore()
var userRef: DocumentReference? = nil
var listener: ListenerRegistration?
override func viewDidLoad() {
super.viewDidLoad()
guard let user = Auth.auth().currentUser else {
return
}
self.user = user
self.userRef = db.collection("users").document(self.user.uid)
startObservingDatabase() //Omitted: Listen processing by addSnapshotListener
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Officially here Auth.auth().Reading currentUser
//However, this is called every time I press a tab, so the collectionView is updated to the latest every time, which is not my intention.
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.listener?.remove()
}
}
LoginViewController.swift
import UIKit
import FirebaseAuth
class LoginViewController: UIViewController {
func signIn() {
//if let tabvc = self.navigationController?.parent as? UITabBarController { //This is nil in the first place
// tabvc.viewControllers?.first?.loadView()
// tabvc.viewControllers?.first?.viewDidLoad()
//}
self.navigationController?.dismiss(animated: true, completion: nil) //This time I happened to have my parents have a NavigationController, so if not, self.dismiss should be OK
}
}