I am attempting to open an app in one of two ways:
- If the user has no
UserDefaults
saved, then open up aWelcomeViewController
- If the user has
UserDefaults
saved, then open up aMenuContainerViewController
as a home page
In step 2, if there are UserDefaults
saved, then I need to log a user in using Firebase
which I have through a function with a completion handler. If step 2 is the case, I want to open MenuContainerViewController
within the completion block without any UI hiccups.
Here is the code I have currently:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
FirebaseApp.configure()
guard
let email = UserDefaults.standard.string(forKey: "email"),
let password = UserDefaults.standard.string(forKey: "password")
else {
// User has no defaults, open welcome screen
let welcomeViewController = WelcomeViewController()
self.window?.rootViewController = welcomeViewController
self.window?.makeKeyAndVisible()
return true
}
// User has defaults saved locally, open home screen of app
let authentificator = Authentificator()
authentificator.login(with: email, password) { result, _ in
if result {
let menuContainerViewController = MenuContainerViewController()
self.window?.rootViewController = menuContainerViewController
self.window?.makeKeyAndVisible()
}
}
return true
}
Here is a video of the current UI, when I need to run the completion handler, the transition is not smooth into the app (there is a brief second with a black screen).
Please help me figure out how to make a smooth app launch.
I've had to handle situations similarly in my Firebase applications. What I typically do is make an
InitialViewController
. This is the view controller that is always loaded, no matter what. This view controller is initially set up to seamlessly look exactly like the launch screen.This is what the
InitialViewController
looks like in the interface builder:And this is what my launch screen looks like:
So when I say they look exactly the same, I mean they look exactly the same. The sole purpose of this
InitialViewController
is to handle this asynchronous check and decide what to do next, all while looking like the launch screen. You may even copy/paste interface builder elements between the two view controllers.So, within this
InitialViewController
, you make the authentication check inviewDidAppear()
. If the user is logged in, we perform a segue to the home view controller. If not, we animate the user onboarding elements into place. The gifs demonstrating what I mean are pretty large (dimension-wise and data-wise), so they may take some time to load. You can find each one below:User previously logged in.
User not previously logged in.
This is how I perform the check within
InitialViewController
: