终止应用程序,由于未捕获的exception'NSInvalidArgumentException' – ios谷歌login

我正在实施从本教程https://developers.google.com/identity/sign-in/ios/sign-in?configured=true&ver=swift取得的Googlelogin过程

正如我在那里看到的那样,作者写道:

在这些例子中,视图控制器是UIViewController的子类。 如果在您的项目中,实现GIDSignInUIDelegate的类不是UIViewController的子类,请实现SignInWillDispatch:error:,signIn:presentViewController:和signIn:dismissViewController:GIDSignInUIDelegate协议的方法。

所以按照他的build议我写了如下:

import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate { func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Initialize sign-in var configureError: NSError? GGLContext.sharedInstance().configureWithError(&configureError) assert(configureError == nil, "Error configuring Google services: \(configureError)") GIDSignIn.sharedInstance().delegate = self return true } // [START openurl] func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { return GIDSignIn.sharedInstance().handleURL(url, sourceApplication: sourceApplication, annotation: annotation) } // [END openurl] @available(iOS 9.0, *) func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { return GIDSignIn.sharedInstance().handleURL(url, sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as! String?, annotation: options[UIApplicationOpenURLOptionsAnnotationKey]) } // [START signin_handler] func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!, withError error: NSError!) { if (error == nil) { print("Signed in!") } else { print("\(error.localizedDescription)") } } // [END signin_handler] // [START disconnect_handler] func signIn(signIn: GIDSignIn!, didDisconnectWithUser user:GIDGoogleUser!, withError error: NSError!) { // Perform any operations when the user disconnects from app here. // [START_EXCLUDE] NSNotificationCenter.defaultCenter().postNotificationName( "ToggleAuthUINotification", object: nil, userInfo: ["statusText": "User has disconnected."]) // [END_EXCLUDE] } 

我也有一个名为LoginScreen.swift的类,其中包含:

 import UIKit class LoginScreen: UIViewController, GIDSignInUIDelegate { override func viewDidLoad() { super.viewDidLoad() GIDSignIn.sharedInstance().uiDelegate = self // Uncomment to automatically sign in the user. GIDSignIn.sharedInstance().signInSilently() } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) GIDSignIn.sharedInstance().uiDelegate = self GIDSignIn.sharedInstance().signInSilently() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func signInWillDispatch(signIn: GIDSignIn!, error: NSError!) { print("Nothing!") } // Present a view that prompts the user to sign in with Google func signIn(signIn: GIDSignIn!, presentViewController viewController: UIViewController!) { self.presentViewController(viewController, animated: true, completion: nil) } // Dismiss the "Sign in with Google" view func signIn(signIn: GIDSignIn!, dismissViewController viewController: UIViewController!) { self.dismissViewControllerAnimated(true, completion: nil) } } 

当我运行应用程序,我看到buttonsign in with google 。 但是当我点击它,我看到错误:

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

这里有什么问题? 我以为我包括了必要的方法

============编辑 – 作为@ emrys57的后续问题:

我的项目中附有GoogleService-Info.plist文件:

在这里输入图像说明

当我注释掉3个方法( presentViewControllerdismissViewControllersignInWillDispatch )没有任何改变 – 我仍然得到相同的错误..

关于屏幕 – 这是我的故事板的样子:

在这里输入图像说明

我想在第三个屏幕上显示googleloginbutton。

这里的第二个屏幕包含一个Tutorial ,其代码如下所示:

 import UIKit class Tutorial: UIViewController { override func viewDidLoad() { super.viewDidLoad() let background = CAGradientLayer().greenBlue() background.frame = self.view.bounds self.view.layer.insertSublayer(background, atIndex: 0) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } 

还有一件事 – 当我打开应用程序,我现在看到谷歌loginbutton:

在这里输入图像说明

而当我点击它 – 我收到提到的错误:

 2016-02-13 09:47:49.578 myapp[20870:800499] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'When |allowsSignInWithWebView| is enabled, uiDelegate must either be a |UIViewController| or implement the |signIn:presentViewController:| and |signIn:dismissViewController:| methods from |GIDSignInUIDelegate|.' *** First throw call stack: (...) 

所以我猜测login画面正在运行,当我按下button…

===========另一个编辑:

当我将LoginScreen的代码复制到类ViewController并在其中添加button时 – 一切正常,我看到一个谷歌loginbutton,我可以login! 但是 – 该button出现在应用程序的第一个屏幕上,这不是我想要的。 我希望它出现在第三个屏幕上(在教程之后)。 有谁知道这里发生了什么,为什么我不能把loginbutton放在第三屏幕上?

我知道这太晚了,但如果你把GIDSignIn.sharedInstance().uiDelegate = self将帮助别人viewDidAppear而不是viewDidLoad,这对我GIDSignIn.sharedInstance().uiDelegate = self

func signIn(signIn: GIDSignIn!, presentViewController viewController: UIViewController!)是一个来自GIDSignInUIDelegate协议的方法,但上面的代码声明AppDelegate采用GIDSignInDelegate (而不是“UI”)协议,而你的GIDSignInUIDelegate不提供这些方法。 或者这些类采用了错误的协议,或者这些方法是错误的类。

不是这个问题的问题,但这也可能是由于自动的Obj-C到Swift 3的命名生成,导致GIDSignInUIProtocol的方法签名与Google的SDK所期望的不同。

将这些转发方法添加到GIDSignInUIProtocol实现将解决此案例的问题 –

 func signIn(signIn: GIDSignIn!, presentViewController viewController: UIViewController!) { self.sign(signIn, present: viewController) } func signIn(signIn: GIDSignIn!, dismissViewController viewController: UIViewController!) { self.sign(signIn, dismiss: viewController) } 

更新了Swift 3:

signIn中使用下面的代码行button操作方法

 GIDSignIn.sharedInstance().uiDelegate = self GIDSignIn.sharedInstance().delegate = self GIDSignIn.sharedInstance().signIn() 

注意:如果您在ViewController中的任何位置使用它,请在代码上面注释…! 否则会没事的。

享受学习….!