2016-10-06 25 views
2

Crashlytics,我们在Google登录过程中收到大量崩溃报告。崩溃报告如下:Swift - uiDelegate必须是UIViewController或实现signIn:presentViewController:&signIn:dismissViewController:方法

Fatal Exception: NSInvalidArgumentException 
uiDelegate must either be a |UIViewController| or implement the |signIn:presentViewController:| and |signIn:dismissViewController:| methods from |GIDSignInUIDelegate|. 

Fatal Exception: NSInvalidArgumentException 
0 CoreFoundation     0x1837f2db0 __exceptionPreprocess 
1 libobjc.A.dylib    0x182e57f80 objc_exception_throw 
2 CoreFoundation     0x1837f2cf8 -[NSException initWithCoder:] 
3 Hello English     0x100583d18 -[GIDSignIn assertValidUIDelegate] (GIDSignIn.m:512) 
4 Hello English     0x1005861dc -[GIDSignIn signInWithOptions:] (GIDSignIn.m:961) 
5 Hello English     0x10058a0e4 -[GIDSignInButton pressed] (GIDSignInButton.m:385) 
6 UIKit       0x188988be8 -[UIApplication sendAction:to:from:forEvent:] 
7 UIKit       0x188988b64 -[UIControl sendAction:to:forEvent:] 
8 UIKit       0x188970870 -[UIControl _sendActionsForEvents:withEvent:] 
9 UIKit       0x188988454 -[UIControl touchesEnded:withEvent:] 
10 UIKit       0x188988084 -[UIWindow _sendTouchesForEvent:] 
11 UIKit       0x188980c20 -[UIWindow sendEvent:] 
12 UIKit       0x18895104c -[UIApplication sendEvent:] 
13 UIKit       0x18894f628 _UIApplicationHandleEventQueue 
14 CoreFoundation     0x1837a909c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ 
15 CoreFoundation     0x1837a8b30 __CFRunLoopDoSources0 
16 CoreFoundation     0x1837a6830 __CFRunLoopRun 
17 CoreFoundation     0x1836d0c50 CFRunLoopRunSpecific 
18 GraphicsServices    0x184fb8088 GSEventRunModal 
19 UIKit       0x1889ba088 UIApplicationMain 
20 Hello English     0x10029b2cc main (AppDelegate.swift:26) 
21 libdispatch.dylib    0x18326e8b8 (Missing) 

我们试过到目前为止:

  1. 感动GIDSignIn.sharedInstance().uiDelegate = selfviewDidLoad()viewDidAppear(animated: Bool)
  2. 我们还实施了GIDSignInUIDelegate所有三种方法没有成功。
  3. 我们的视图控制器不是UIViewController的直接子,但现在它是和崩溃仍在计数。
  4. 我们使用的是简单的UIButton,所以我们认为这可能是导致崩溃的原因(尽管不合逻辑但我们尝试过);我们将其更改为GIDSignInButton,但没有减少碰撞计数。

现在我们已经删除了Google Login进程,但这不是解决方案。奇怪的是,我们无法在我们的最后再现这次崩溃;我们只在Crashlytics上遇到这些崩溃。

那么任何人有任何解决方案?

+0

你为什么不定义代表? –

+0

看到编辑,我们也试过了。 –

+0

看到这个http://stackoverflow.com/questions/35371393/terminating-app-due-to-uncaught-exception-nsinvalidargumentexception-ios-goo –

回答

2

最后,付出了很多努力找到了解决办法。 我的环境是

斯威夫特3,

的iOS 10.3.x中,

的Xcode 8.3.2

在这里发帖的完整解决方案

import UIKit 
import GoogleSignIn 

class ViewController: UIViewController, GIDSignInUIDelegate, GIDSignInDelegate { 

    @IBOutlet weak var signInButton: UIButton! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // set delegates 
     GIDSignIn.sharedInstance().delegate = self 
     GIDSignIn.sharedInstance().uiDelegate = self 

     let buttonFrame : CGRect = CGRect.init(x: 0, y: 0, width: 100, height: 50) 
     let gdSignInButton = GIDSignInButton.init(frame:buttonFrame) 
     gdSignInButton.center = view.center 
     view.addSubview(gdSignInButton) 

     // gdSignInButton.addTarget(self, action: #selector(self.didTapSignOut(sender: self.gdSignInButton)), for: UIControlEvents.touchUpInside) 
    } 

    @IBAction func didTapSignOut(sender: GIDSignInButton) { 
     GIDSignIn.sharedInstance().signOut() 
    } 

    func sign(inWillDispatch signIn: GIDSignIn!, error: Error!) { 

     guard error == nil else { 

      print("Error while trying to redirect : \(error)") 
      return 
     } 

     print("Successful Redirection") 
    } 


    //MARK: GIDSignIn Delegate 

    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! 
      print("User id is \(userId)") 

      let idToken = user.authentication.idToken // Safe to send to the server 
      print("Authentication idToken is \(idToken)") 
      let fullName = user.profile.name 
      print("User full name is \(fullName)") 
      let givenName = user.profile.givenName 
      print("User given profile name is \(givenName)") 
      let familyName = user.profile.familyName 
      print("User family name is \(familyName)") 
      let email = user.profile.email 
      print("User email address is \(email)") 
      // ... 
     } else { 
      print("ERROR ::\(error.localizedDescription)") 
     } 
    } 

    // Finished disconnecting |user| from the app successfully if |error| is |nil|. 
    public func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) 
    { 

    } 



} 

和我的AppDelegate这个样子。

import UIKit 
import Google 
import GoogleSignIn 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

     // Initialize sign-in 
     var configureError: NSError? 
     GGLContext.sharedInstance().configureWithError(&configureError) 
     assert(configureError == nil, "Error configuring Google services: \(configureError)") 



     return true 
    } 

    func applicationWillResignActive(_ application: UIApplication) { 
     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 
    } 

    func applicationDidEnterBackground(_ application: UIApplication) { 
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
    } 

    func applicationWillEnterForeground(_ application: UIApplication) { 
     // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 
    } 

    func applicationDidBecomeActive(_ application: UIApplication) { 
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
    } 

    func applicationWillTerminate(_ application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
    } 


    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { 
     return GIDSignIn.sharedInstance().handle(url as URL!, 
               sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String, annotation: options[UIApplicationOpenURLOptionsKey.annotation]) 
    } 


} 
+0

您的解决方案有什么不同?而且,你在哪里调用了'GIDSignIn.sharedInstance()。signIn()' –

0

,我(的iOS 10.0)溶液分配我的视图控制器作为其viewDidAppear UI委托:方法...

-(void)viewDidAppear{ 
    [super viewDidAppear]; 
    [GIDSignIn sharedInstance].uiDelegate = self; 
} 
1

你需要实现谷歌的代表和火力正确
在viewDidLoad中添加这样

class ViewController: UIViewController, GIDSignInDelegate,GIDSignInUIDelegate  

添加这些行

GIDSignIn.sharedInstance().uiDelegate = self 
GIDSignIn.sharedInstance().delegate = self 
GIDSignIn.sharedInstance().signIn() 
相关问题