I'm trying to set up the latest GoogleSignIn with SwiftUI. Official Firebase documentation offers outdated approach designed for UIKit, ViewControllers and AppDelegate, so there is simply no way to find out what workaround is needed to make it work. I was able to implement UIApplicationDelegateAdaptor to get access to didFinishLaunchingWithOptions method to configure FirebaseApp and GIDSignIn. While following this documentation: https://firebase.google.com/docs/auth/ios/google-signin I ultimately stuck on the step 4. It's unclear where do I have to use this code or how to integrate it into SwiftUI paradigm:
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)
// ...
}
I'm aware of this guide from Google: https://developers.google.com/identity/sign-in/ios/quick-migration-guide but there is no code example of how to do it properly.
CodePudding user response:
You would probably want to run that code as the result of an action the user takes. After pressing a Button
, for example.
The tricky part is going to be that GIDSignIn.sharedInstance.signIn
wants a UIViewController
for its presenting
argument, which isn't necessarily straightforward to get in SwiftUI. You can use a UIViewControllerRepresentable
to get a reference to a view controller in the hierarchy that you can present from.
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)
}
}
}
}