2016-10-06 3 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. 우리는 또한 성공하지 GIDSignInUIDelegate의 세 가지 방법을 구현했습니다 viewDidAppear(animated: Bool)
  2. viewDidLoad()에서 GIDSignIn.sharedInstance().uiDelegate = self을 이전 다음과 같이 충돌 보고서입니다.
  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,

아이폰 OS 10.3.x에서,

엑스 코드 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에 같이

입니다 . 제대로
은 Google의 위임을 구현해야하는 방법 ...

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

솔루션에서 다른 점은 무엇입니까? 그리고, 당신은 어디에서'GIDSignIn.sharedInstance(). signIn()'을 호출 했습니까? –

0

나를 위해 솔루션 (아이폰 OS 10.0) 내보기의 viewDidAppear의 UI 위양 등의 컨트롤러를 할당했다 있는 viewDidLoad이

class ViewController: UIViewController, GIDSignInDelegate,GIDSignInUIDelegate  

같은 추가 을 다음 라인을 추가

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

및 중포 기지 :

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]) 
    } 


} 
관련 문제