6

I am trying to launch google login from AppDelegate.swift and then launch my app's main screen upon login success.

enter image description here

I am able to

  1. show the google login button as shown above

  2. the user is sent to google to sign in

  3. the user is sent back to original (step 1)

After step 3. I'd like to send the user to my app's main page.

My code is below. The problem I'm having is that authUI is not being called.

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, FIRAuthUIDelegate { var window: UIWindow? var authUI: FIRAuthUI? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { FIRApp.configure() authUI = FIRAuthUI.defaultAuthUI() authUI?.delegate = self let providers: [FIRAuthProviderUI] = [FIRGoogleAuthUI()] authUI?.providers = providers // show google login button let authViewController = authUI?.authViewController() self.window = UIWindow(frame: UIScreen.mainScreen().bounds) self.window?.rootViewController = authViewController self.window?.makeKeyAndVisible() return true } func application(application: UIApplication, openURL url: NSURL, options: [String: AnyObject]) -> Bool { return GIDSignIn.sharedInstance().handleURL(url, sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as? String, annotation: options[UIApplicationOpenURLOptionsAnnotationKey]) } func authUI(authUI: FIRAuthUI, didSignInWithUser user: FIRUser?, error: NSError?) { // launch main view controller } } 

EDIT: This appears to be a duplicate of another question. The other question's title is quite general and only gets to the details a few lines deep. In any case, I believe Chris's answer is more thorough than the one there. I think both the question and answers here are clearer, more pointed and more thorough so it would be a mistake to just direct people here to go there as would happen if this was marked as a duplicate.

4
  • Are you using storyboard? Commented Oct 27, 2016 at 22:41
  • When you say that your authUI isn't getting called, you mean the authUI delegate method yeah? Commented Oct 28, 2016 at 10:14
  • Yes, the one shown in the code above. Commented Oct 28, 2016 at 12:46
  • I take it you have logged both the error and the user object returned in the function just to check? Commented Oct 28, 2016 at 17:09

2 Answers 2

7
+50

I think your problem lies here, in the - (void)signInWithProviderUI:(id<FIRAuthProviderUI>)providerUI method.

The delegate method is called in the dismissViewControllerAnimated:completion: completion block.

[self.navigationController dismissViewControllerAnimated:YES completion:^{ [self.authUI invokeResultCallbackWithUser:user error:error]; }]; 

As you can see from the Apple docs, this method is expected to be called on a modally presented viewController. You are displaying it as a root view controller. Try displaying it with a modal from a UIViewController, and things should work out. To debug this try and set a breakpoint at line 193 to see that it won't get hit. I would be very surprised if this doesn't work when you display the authController modally.

To come up with a possible solution to your problem (I am assuming you want to ensure a user is signed in before using your app). The below is a simplification of what I am using in an app currently.

EDIT: Updated for the new 1.0.0 FirebaseUI syntax.

class MainTabController: UITabBarController, FIRAuthUIDelegate { let authUI: FUIAuth? = FUIAuth.defaultAuthUI() override func viewDidLoad() { super.viewDidLoad() var authProviders = [FUIFacebookAuth(), FUIGoogleAuth()] authUI.delegate = self authUI.providers = authProviders //I use this method for signing out when I'm developing //try! FIRAuth.auth()?.signOut() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if !isUserSignedIn() { showLoginView() } } private func isUserSignedIn() -> Bool { guard FIRAuth.auth()?.currentUser != nil else { return false } return true } private func showLoginView() { if let authVC = FUIAuth.defaultAuthUI()?.authViewController() { present(authVC, animated: true, completion: nil) } } func authUI(_ authUI: FUIAuth, didSignInWith user: FIRUser?, error: Error?) { guard let user = user else { print(error) return } ... } 
Sign up to request clarification or add additional context in comments.

3 Comments

Can you do the above code in objective c ? stackoverflow.com/questions/42340641/…
Afraid not @S.Sallay :/
Ran into a problem here where trying to set authUI to FUIAuth.defaultAuthUI() the way you have caused an exception because it was being executed before the FirebaseApp.configure() method executed in applicationDidFinishLaunchingWithOptions. A bit strange, but initializing the value in viewDidLoad() instead fixed the problem for me.
1

It must be a problem of reference.

class AppDelegate: UIResponder, UIApplicationDelegate, FIRAuthUIDelegate { var window: UIWindow? let authUI = FIRAuthUI.defaultAuthUI() func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { FIRApp.configure() authUI.delegate = self let providers: [FIRAuthProviderUI] = [FIRGoogleAuthUI()] authUI.providers = providers // show google login button let authViewController = authUI.authViewController() self.window = UIWindow(frame: UIScreen.mainScreen().bounds) self.window?.rootViewController = authViewController self.window?.makeKeyAndVisible() return true } } 

Try this. AppDelegate will hold the reference of authUI and its delegate.

2 Comments

making the exact change you wrote let authUI = FIRAuthUI.defaultAuthUI() caused authUI to be nil, which resulted in "Applications are expected to have a root view controller at the end of application launch". I've changed my code by pulling the reference to a higher level but authUI is still not being run.
The warning doesn't mean authUI is nil. it means window doesn't have rootViewController till application launch finished. There are two possibility. One is authUI.authViewController() returns nil and the other possibility is authUI.authViewController() is async and takes too long time. Check authUI.authViewController()'s return is not nil.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.