Crashlytics
から、Googleログインプロセスで大量のクラッシュレポートを受け取っています。クラッシュレポートは次のとおりです。
_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)
_
これまでに試しました:
GIDSignIn.sharedInstance().uiDelegate = self
をviewDidLoad()
からviewDidAppear(animated: Bool)
に移動しましたGIDSignInUIDelegate
の3つのメソッドすべてを実装しましたが、成功しませんでした。UIViewController
の直接の子ではありませんでしたが、現在はそうであり、クラッシュはまだカウントされています。UIButton
を使用していたので、それがクラッシュの原因である可能性があると考えました(非論理的ですが、試しました)。 GIDSignInButton
に変更しましたが、クラッシュ数は減少しませんでした。今のところ、_Google Login
_プロセスを削除しましたが、それは解決策ではありません。そして奇妙なことに、このクラッシュを最後に再現することはできません。これらのクラッシュはCrashlytics
でのみ発生します。
だから誰かが解決策を持っていますか?
最後に多くの努力をした後、解決策を見つけました。私の環境は
スウィフト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])
}
}
これらの行は、viewWillAppear
のUIViewController
メソッドで記述する必要があります。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().delegate = self
}
delegate of theGoogleとfirebaseを適切に実装する必要があります
このように追加
class ViewController: UIViewController, GIDSignInDelegate,GIDSignInUIDelegate
viewDidLoadにこれらの行を追加します
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().signIn()
以下を含めるだけです
func sign(_ signIn: GIDSignIn!, dismiss viewController: UIViewController!) {
print("dismissing Google SignIn")
}
func sign(_ signIn: GIDSignIn!, present viewController: UIViewController!) {
print("presenting Google SignIn")
}
この行をviewDidAppearに追加する必要があります。
override func viewDidAppear(_ animated: Bool) {
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
}
このエラーは、カスタムビューコントローラークラスをストーリーボードでUIViewControllerTookに設定するのを忘れた場合にも表示されます。
これを行うには->ストーリーボードに移動します-> ViewControllerを選択します-> Identity Explorerに移動し、空白の場合はクラスを設定します
以下の画像を参照してください
私の解決策(iOS 10.0)は、viewDidAppear:メソッドでビューコントローラーをUIデリゲートとして割り当てることでした...
-(void)viewDidAppear{
[super viewDidAppear];
[GIDSignIn sharedInstance].uiDelegate = self;
}
これは単に、次のデリゲートメソッドを実装する必要があることを意味します。
_GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
_
これはviewDidLoad()
で設定できます。
複数のViewController(登録画面やログイン画面など)でGoogleサインインを使用している場合は、画面が変更されたときに代理人を更新する必要があります。競合を避けるために、viewDidAppear()
に設定することをお勧めします。これにより、画面を前後に切り替える場合に、デリゲート参照が現在のViewControllerで更新されます。
私もこのエラーに遭遇し、2つのケースでそれを観察しました:
GoogleSignInボタンの@IBActionを作成し、次の両方の行を含めました。
@IBAction func googleSignInButton(_ sender:Any){GIDSignIn.sharedInstance()。signIn()GIDSignIn.sharedInstance()。uiDelegate = self}
ただし、uiDelegateの割り当ては、@ IBActionではなく、viewDidLoadにある必要があります。
GIDSignIn.sharedInstance().uiDelegate = self
根本的な原因は、新しいUIViewControllerクラス「DoLoginVC.Swift」を作成したことですが、このカスタムクラスをストーリーボードのUIViewControllerにマップしませんでした。見落とし。カスタムクラスマッピングを追加した後、すべてが機能し始めました。
このエラーが表示された場合は、ストーリーボードに移動してViewControllerに移動し、添付のスクリーンショットのようにカスタムクラスを指定したことを確認してください。
GoogleSignIn SDK 5.以降ではGIDSignInUIDelegate
が取り消されました
だから代わりに
GIDSignIn.sharedInstance().uiDelegate = self
ログインビューの表示に準拠するために、以下の行を追加します
GIDSignIn.sharedInstance()?.presentingViewController = self