ios - 如何将应用程序的呈现 View Controller 和客户端 ID 传递给 Google Sign In 登录方法

标签 ios swift firebase uikit google-signin

您好,我一直在关注 ( https://firebase.google.com/docs/auth/ios/google-signin ) 在 iOS 应用中使用 Firebase 设置简单的 Google SignIn。我使用 Xcode 12.5.1。我创建了一个新的 Storyboard (UIKit) 应用程序。我执行了 pod init 并添加了 Firebase 和 GoogleSignIn,并执行了 pod install

我在 iOS 方面也是个菜鸟。

我正在尝试遵循这些步骤,但对于所有步骤,它都没有真正解释将代码放在哪里。对于某些我认为我成功了,但对于第 4 步。我不知道该代码放在哪里。我尝试寻找其他帖子/教程来使用 Firebase 和 SwiftUI 设置 GoogleSignIn,但没有一个有效。步骤看起来很简单,但它们可能省略了一些 iOS 菜鸟不知道的非常简单的东西。

请至少解释一下第 4 步。

你们中的一些人评论说将其放入AppDelegate中。我已经创建了 AppDelegate,但不确定将其放在哪里。在 AppDelegate 中创建用于转储步骤 4 中的代码的登录函数不起作用。我还尝试用 UIViewControllerRepresentable 包装它,如 here遇到同样的问题。

它提示这个 presenting: self 来自 GIDSignIn.sharedInstance.signIn(with: config,presenting: self) { [unowned self] user, error in (code从步骤 4 开始,我不知道该放在哪里)是 AppDelegate,无法转换为预期的 UIViewController。

import SwiftUI
import Firebase
import GoogleSignIn

@main
struct FolderlesApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}


class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        
        FirebaseApp.configure()
        
        return true
    }
    
    @available(iOS 9.0, *)
    func application(_ application: UIApplication, open url: URL,
                     options: [UIApplication.OpenURLOptionsKey: Any])
      -> Bool {
      return GIDSignIn.sharedInstance.handle(url)
    }
}

最佳答案

我认为您在提供的代码中使用的是 SwfitUI 而不是 UIkit。如果这是真的。我可以回答 SwiftUI 解决方案。

假设您已设置第 1 步(网址类型)并导入 GoogleService-Info.plist。如果不这样做,请务必先这样做。

然后,我们必须在 SwiftUI 中自己创建 AppDelegate。您可以将此代码添加到您的“App”类型结构文件中(通常,文件名是您的 Project_NameApp.swift)。就像下面的例子一样。这是 Authenticate Using Google Sign-In on iOS  |  Firebase 中的步骤 2、步骤 3

// Project_NameApp.swift
struct Project_NameApp: App {
    // add this var define line
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    let persistenceController = PersistenceController.shared
    
    var body: some Scene {
        WindowGroup {
                TestLoginView()
        }
    }
}

// add this class
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // add this function for init FirebassApp 
        FirebaseApp.configure()
        return true
    }
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
           // add this function for Google Sign in to handle the url
        return GIDSignIn.sharedInstance.handle(url)
    }
}

下一个是你的主要问题 - 第 4 步的代码应该放在哪里?以下代码是您想要使用 google 登录的示例 SwiftUI View 。您可以看到它只是将第 4 步的代码转换为函数,并绑定(bind)到您希望用户点击的按钮并使用 Google 帐户登录。

import SwiftUI
import GoogleSignIn
import Firebase

struct TestLoginView: View {
    var body: some View {
        VStack {
            Button(action: {
                   // Just add the action function, it will works.
                googleSignIn()
            }, label: {
                Text("Google Sign In")
            })
        }
    }
    
    func googleSignIn(){
        guard let clientID = FirebaseApp.app()?.options.clientID else { return }
        
        // Create Google Sign In configuration object.
        let config = GIDConfiguration(clientID: clientID)
        
        // Start the sign in flow!
        GIDSignIn.sharedInstance.signIn(with: config, presenting: (UIApplication.shared.windows.first?.rootViewController)!) { user, error in

          if let error = error {
            print(error.localizedDescription)
            return
          }

          guard
            let authentication = user?.authentication,
            let idToken = authentication.idToken
          else {
            return
          }

            let credential = GoogleAuthProvider.credential(withIDToken: idToken,
                            accessToken: authentication.accessToken)

            // Authenticate with Firebase using the credential object
            Auth.auth().signIn(with: credential) { (authResult, error) in
                if let error = error {
                    print("authentication error \(error.localizedDescription)")
                    return
                }
                print(authResult ?? "none")
            }
        }
    }
}

struct TestLoginView_Previews: PreviewProvider {
    static var previews: some View {
        TestLoginView()
    }
}

我已经在我的 Xcode 上测试了它,它对我有用。你可以尝试一下,希望能解决问题!

Tips 1: This is just a simple code. If you want a better implementation. I recommend you implement with MVVM structure. In this case, you should put the function into your ViewModel which you create by yourself. The button should call the Google Sign in function in your ViewModel.

Tips 2: This code doesn’t implement the multi-factor login with phone verify, check out this article for more detail. Most use case won’t use this less frequently used multi-factor login.

关于ios - 如何将应用程序的呈现 View Controller 和客户端 ID 传递给 Google Sign In 登录方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68520136/

相关文章:

ios - 当 viewController 转到另一个 tableViewController 时,我如何保存字符串的值

ios - Xcode 6 测试版 4 : Use of Unresolved Identifier 'NSFetchedResultsChangeInsert'

ios - 现有目标没有 'swift compiler code generation' 部分

ios - 将变量从 tableView 传递到 prepareForSegue?

firebase - Flutter:可以等待同级小部件完成构建吗?

ios - 错误 : UITableView jump to top with UITableViewAutomaticDimension

ios - 我可以创建一个我所有的 View Controller 都可以访问的类吗

debugging - 是否可以像我们在节点中那样使用 --inspect-brk 启动 firebase 服务?

javascript - 为什么 Google Cloud Function 在部署后多次运行全局函数?

ios - 按下页面时执行 Segue