¿Cómo configurar Firebase Google SignIn 6.0.2 usando la arquitectura SwiftUI 2.0?

1

Estoy intentando configurar la última versión de GoogleSignIn con SwiftUI. La documentación oficial de Firebase ofrece un enfoque desactualizado diseñado para UIKit, ViewControllers y AppDelegate, por lo que simplemente no hay forma de averiguar qué solución se necesita para que funcione. Pude implementar UIApplicationDelegateAdaptor para obtener acceso al método didFinishLaunchingWithOptions para configurar FirebaseApp y GIDSignIn. Mientras seguía esta documentación: https://firebase.google.com/docs/auth/ios/google-signin Finalmente me quedé en el paso 4. No está claro dónde tengo que usar este código o cómo integrarlo en el paradigma SwiftUI :

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: self) { [unowned self] user, error in

  if let error = error {
    // ...
    return
  }

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

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

  // ...
}

Conozco esta guía de Google: https://developers.google.com/identity/sign-in/ios/quick-migration-guide pero no hay un ejemplo de código de cómo hacerlo correctamente.

1

Probablemente desee ejecutar ese código como resultado de una acción que realiza el usuario. Después de presionar a Button, por ejemplo.

La parte complicada será que GIDSignIn.sharedInstance.signInquiere un argumento UIViewControllerpara su presentingargumento, que no es necesariamente sencillo de obtener en SwiftUI. Puede usar a UIViewControllerRepresentablepara obtener una referencia a un controlador de vista en la jerarquía desde el que puede presentar.

class LoginManager : ObservableObject {
    var viewController : UIViewController?
    
    func runLogin() {
        guard let viewController = viewController else {
            fatalError("No view controller")
        }
        
        //Other GIDSignIn code here. Use viewController for the `presenting` argument
    }
}

struct DummyViewController : UIViewControllerRepresentable {
    var loginManager : LoginManager
    
    func makeUIViewController(context: Context) -> some UIViewController {
        let vc = UIViewController()
        loginManager.viewController = vc
        return vc
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
}

struct ContentView : View {
    @StateObject private var loginManager = LoginManager()
    
    var body: some View {
        VStack(spacing: 0) {
            Button(action: {
                loginManager.runLogin()
            }) {
                Text("Login")
                DummyViewController(loginManager: loginManager)
                    .frame(width: 0, height: 0)
            }
        }
    }
}
2
  • ¡Gracias por una rápida respuesta! Según tengo entendido, no hay otra forma más que tener que usar UIViewControllerRepresentable en mi caso. 14 de oct a las 0:13
  • 1
    También puede intentar obtener una referencia a un controlador de vista desde el window, pero eso puede ser problemático en aplicaciones modernas basadas en escenas donde no hay necesariamente una ventana. Otra opción es usar algo como SwiftUI-Introspect, pero personalmente prefiero usar UIViewControllerRepresentable que introducir una dependencia de terceros.
    jnpdx
    14 de octubre a las 0:15