Google Sign In 调用 App Delegate 中的方法后关闭 View Controller (iOS / Swift)

Posted

技术标签:

【中文标题】Google Sign In 调用 App Delegate 中的方法后关闭 View Controller (iOS / Swift)【英文标题】:Dismiss View Controller after Google Sign In calls methods in App Delegate (iOS / Swift) 【发布时间】:2019-08-26 04:28:58 【问题描述】:

我已经在我的项目中实现了 Google 登录,其中我有一个视图控制器来处理以模态方式呈现的登录。谷歌登录按钮调用应用程序委托中的方法。

我希望能够在用户登录后关闭视图控制器,但我不知道如何执行此操作。 图片在这里:https://i.imgur.com/5N89wUb.png

dismiss() 不能从应用委托中调用。我尝试在我的登录视图控制器中放置一个函数来检查用户是否已登录,但这不会运行,因为登录过程是异步运行的(更不用说一个非常hacky的方法)

//Code on the Login VC:
override func viewDidLoad() 
    super.viewDidLoad()

    //Google Sign in stuff

    GIDSignIn.sharedInstance()?.presentingViewController = self
    // Automatically sign in the user.
    GIDSignIn.sharedInstance()?.restorePreviousSignIn()
    ...

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

...

    GIDSignIn.sharedInstance().clientID = "my-client-id.apps.googleusercontent.com"
    GIDSignIn.sharedInstance().delegate = self

...

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool 

    let googleDidHandle = GIDSignIn.sharedInstance().handle(url)
    let facebookDidHandle = ApplicationDelegate.shared.application(app, open: url, options: options)
    return facebookDidHandle || googleDidHandle


func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
          withError error: Error!) 
    if let error = error 
        if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue 
            print("The user has not signed in before or they have since signed out.")
         else 
            print("\(error.localizedDescription)")
        
        return
    
    guard let idToken = user.authentication.idToken else  fatalError("couldn't get idToken")// Safe to send to the server

    googleSignIn(idToken: idToken)

...

用户登录后,我想关闭模态呈现的视图控制器,但我不知道如何通过应用委托来执行此操作。

【问题讨论】:

【参考方案1】:

您必须设置 uiDelegate 以获取有关 google 登录控制器存在或关闭的信息。

GIDSignIn.sharedInstance().uiDelegate = self

然后需要在你的类中实现GIDSignInUIDelegate

extension ViewController: GIDSignInUIDelegate 

//MARK: GoogleSignIn UI Delegate

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


public func sign(_ signIn: GIDSignIn!,
                 present viewController: UIViewController!) 


public func sign(_ signIn: GIDSignIn!,
                 dismiss viewController: UIViewController!) 
    dismiss(animated: true, completion: nil)


使用这些方法,您可以关闭您的 ViewController

【讨论】:

【参考方案2】:

当用户点击使用 Google 登录按钮时。您可以调用以下方法。

@objc func didTapGooglePlusLoginButton(sender:UIButton)  
        GIDSignIn.sharedInstance().signIn()
    

您可以在 Login VC 中实现 GIDSignInDelegate 并在 Login VC 本身中添加 didSignInFor 委托方法,以便您可以处理输入和输出。

class LoginVC: UIViewController,GIDSignInDelegate 

你可以在下面的函数中解散或移动到另一个类

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) 
        if (error == nil) 
            print(user.profile)
            let userId = user.userID                  
            self.Name = user.profile.name
            self.givenName = user.profile.givenName
            self.Email = user.profile.email
            let navigationController =  UINavigationController(rootViewController: VC)
            appDelegate?.window?.rootViewController = navigationController
            // ...dissmiss or move to another controller
        
        else 
            print("\(String(describing: error))")
        
    

【讨论】:

【参考方案3】:

感谢你们提供的信息……你们让我走上了正轨!

这是我针对最新(2019 年 8 月)Google Sign In Swift SDK 的解决方案,因为在委托名称等方面有一些细微的变化。

所以基本上,将登录视图控制器设置为 GIDSignInDelegate:

class LoginController: UIViewController, GIDSignInDelegate 

...

将以下内容放入 viewDidLoad:

override func viewDidLoad() 
    super.viewDidLoad()

//Google Sign in stuff
GIDSignIn.sharedInstance().clientID = "your-client-id.apps.googleusercontent.com"
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance()?.presentingViewController = self
// Automatically sign in the user.
GIDSignIn.sharedInstance()?.restorePreviousSignIn()

...

并在您的登录视图控制器中实现以下功能(根据谷歌文档)

@available(ios 9.0, *)
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool 
  return GIDSignIn.sharedInstance().handle(url)


func application(_ application: UIApplication,
                 open url: URL, sourceApplication: String?, annotation: Any) -> Bool 
  return GIDSignIn.sharedInstance().handle(url)


func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
          withError error: Error!) 
  if let error = error 
    if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue 
      print("The user has not signed in before or they have since signed out.")
     else 
      print("\(error.localizedDescription)")
    
    return
  
  // 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
  // ...


func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!,
          withError error: Error!) 
  // Perform any operations when the user disconnects from app here.
  // ...

【讨论】:

【参考方案4】:

我想你已经错过了这种写入 `appdelegate' 文件的方法。请检查以下方法。

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool 

        let isGoogle = GIDSignIn.sharedInstance().handle(url as URL?, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
        return isFB || isGoogle
    

有关更多 google 登录信息,请查看以下链接:Github link 如果对您有帮助,请点击开始 :) 以便其他人轻松找到它。

编码愉快:)

【讨论】:

以上是关于Google Sign In 调用 App Delegate 中的方法后关闭 View Controller (iOS / Swift)的主要内容,如果未能解决你的问题,请参考以下文章

使用 google_sign_in Flutter 刷新令牌获取新令牌

如何在 Flutter 的 google_sign_in 中获取 JWT 格式的访问令牌?

Google Play 游戏登录已取消,状态码为 SIGN_IN_REQUIRED

Android:Google 登录 - “DEFAULT_SIGN_IN”和“DEFAULT_GAMES_SIGN_IN”之间的区别

扑动 google_sign_in 崩溃:__exceptionPreprocess + 294

Flutter web google_sign_in:如何检索refreshToken