lf215 lf215 - 1 month ago 20
Swift Question

iOS firebase: FIRAuthUIDelegate.authUI not being called

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.

Answer

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.

class MainTabController: UITabBarController, FIRAuthUIDelegate {

    var authUI: FIRAuthUI = FIRAuthUI.default()

    override func viewDidLoad() {
        super.viewDidLoad()
        var authProviders = [FIRFacebookAuthUI(), FIRGoogleAuthUI()]
        authUI.delegate = self
        authUI.providers = authProviders

        //Is 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 = FIRAuthUI.default()?.authViewController() {
        present(authVC, animated: true, completion: nil)
      }
   }
    func authUI(_ authUI: FIRAuthUI, didSignInWith user: FIRUser?, error: Error?) {
        guard let user = user else {
            print(error)
            return
        }

        ...
    }