0
votes

I work with google signIn Api, when I click on my login button on my first view I got the google webview page, I can log myself and get my data, after I use performe for segue to access to the 2nd view. When I try to logout in the the 2nd view, he print my string "deco", and I go back to my first page. But when I try to log myself again, he crash with this error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'uiDelegate must either be a |UIViewController| or implement the |signIn:presentViewController:| and |signIn:dismissViewController:| methods from |GIDSignInUIDelegate|.'

I think the logout function didn't work, and also I don't think use performe for segue in the appDelegate is the best methode, do you make it with something else ? (Expect Notification)

My firstViewController

class ViewController: UIViewController, GIDSignInUIDelegate{

override func viewDidLoad() {
    super.viewDidLoad()
    GIDSignIn.sharedInstance().uiDelegate = self
    // Do any additional setup after loading the view, typically from a nib.
}

@IBAction func btn(_ sender: Any) {
    GIDSignIn.sharedInstance().signIn()
}}

In my second view I have the same thing, only change is GIDSignIn.sharedInstance().disconnect()

My appDelegate contain

class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        var configureError : NSError?
        GGLContext.sharedInstance().configureWithError(&configureError)
        if (configureError != nil)
        {
                print("We have an error ! \(configureError)")
        }
        else
        {
            print("Google ready sir !")

        }
        GIDSignIn.sharedInstance().delegate = self

        return true
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        return GIDSignIn.sharedInstance().handle(
            url,
            sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String,
            annotation: options[UIApplicationOpenURLOptionsKey.annotation])
    }
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!)
    {
        if (error == nil) {
            // Perform any operations on signed in user here.
            let userId = user.userID                  // For client-side use only!
            let idToken = user.authentication.accessToken // Safe to send to the server
            let fullName = user.profile.name
            let givenName = user.profile.givenName
            let familyName = user.profile.familyName
            let email = user.profile.email
            print("userId =>\(userId)")
            print("idToken =>\(idToken)")
            print("fullName =>\(fullName)")
            print(" familyName=>\(familyName)")
            print(" givenName=>\(givenName)")
            print("email =>\(email)")
            print("info => \(user.authentication)")
            guard let rvc = self.window?.rootViewController as? ViewController
                else {
                    return
            }
            rvc.performSegue(withIdentifier: "test", sender: nil)



        } else {
            print("\(error.localizedDescription)")
        }
    }



    func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!)
    {
        print("Deco")
    }
    // Other func not usefull
}
1

1 Answers

0
votes

Looks like you declared both your ViewController and your AppDelegate as implementing GIDSignInUIDelegate but you only put the implementation in AppDelegate.

You should decide whether you want the implementation in one or the other, and only declare the protocol supported there. My guess is that you are crashing because the ViewController is the actual delegate:

 GIDSignIn.sharedInstance().uiDelegate = self

but it doesn't have the required methods. If you look at the Google docs here, you can see that it recommends you implement in the AppDelegate. This contains a number of steps. The first step is the set the uiDelegate to your AppDelegate instance instead. Something like:

GIDSignIn.sharedInstance().uiDelegate = UIApplication.shared.delegate as? GIDSignInUIDelegate

Then add the implementation:

func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,
  withError error: NSError!) {
    if (error == nil) {
      // Perform any operations on signed in user here.
      let userId = user.userID                  // For client-side use only!
      let idToken = user.authentication.idToken // Safe to send to the server
      let fullName = user.profile.name
      let givenName = user.profile.givenName
      let familyName = user.profile.familyName
      let email = user.profile.email
      // ...
    } else {
      print("\(error.localizedDescription)")
    }
}

func signIn(signIn: GIDSignIn!, didDisconnectWithUser user:GIDGoogleUser!,
  withError error: NSError!) {
    // Perform any operations when the user disconnects from app here.
    // ...
}