[SWIFT] uitabbarcontroller reload after login with FirebaseAuth

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.

Premise

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

Review of view life cycle

https___qiita-image-store.s3.amazonaws.com_0_326574_354ea62b-ca5a-1136-4524-de841e7d7b89.png

Home collectionView does not update after login

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.

Solutions

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

Whole code

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

reference

Recommended Posts

uitabbarcontroller reload after login with FirebaseAuth
How to redirect after user login with Spring-security
SNS login with Spring Boot
Implement jCaptcha reload with ajax
Login function with Spring Security
Login function implementation with rails