google / google/GoogleSignIn-iOS
Using v6 in SwiftUI: `.signIn()` workaround and suggestions for SwiftUI support
- Dominant language
- Objective-C
- Stars
- 750
- Forks
- 282
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 9
Description
## Background
With SwiftUI being the way forward for iOS dev, I would have hoped GoogleSignIn had better support for SwiftUI.
Unfortunatley there isn't any SwiftUI-focused documentation, and the patterns changed in v6 (e.g., no delegates) seem to make implementing GIDSignIn harder in SwifUI.
The biggest issue I've had (and clearest example) is below:
## Sign In
The main issue I've run into is with this function:
```swift
- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
callback:(nullable GIDSignInCallback)callback;
```
SwiftUI doesn't have view controllers, but we need to instantiate _a_ sign-in view from SwiftUI.
There's two workarounds:
1. Create a `UIViewRepresentable` view that accesses the root view controller with something like `UIApplication.shared.windows.last?.rootViewController`
1. Create a `UIViewRepresentable` view that instantiates a dummy `UIViewController` that then calls some `AuthManager` singleton, which in turn calls `sharedInstance.signIn(...)`.
This is so confusing to implement primarily because there _already existed_ a delegate pattern and a non-`presentingVC` parameter [before v6 of this library](https://developers.google.com/identity/sign-in/ios/quick-migration-guide).
Tying it all together would be something like this:
```swift
// AuthManager.swift
class AuthManager {
var shared = AuthManager()
var config = GIDConfiguration()
func signIn(withVC vc: UIViewController) {
GIDSignIn.signIn(with: config, presenting: vc) { /* ... */ }
}
}
// AuthWrapper.swift
class AuthVC: UIViewController {
func signIn() {
AuthManager.shared.signIn(withVC: self)
}
}
class AuthVCWrapper: UIViewRepresentable {
let authVC = AuthVC() // strong ref
func makeUIViewController() {
return authVC
}
func signIn() {
authVC.signIn() // single responsibility principle
}
}
// SignIn.swift
class SignIn: View {
var authWrapper = AuthVCWrapper()
var body: some View {
ZStack {
authWrapper
Button(action: authWrapper.signIn()) {
Text("Sign In")
}
}
}
}
```
To me personally this seems verbose.
## Delegates
In addition, the delegate pattern [seems to have been removed](https://developers.google.com/identity/sign-in/ios/quick-migration-guide). This would have made it much easier to work alongside a more detached MVVM pattern instead of routing everything through the `sharedInstance` singleton anyways.
Is there a reason for why the delegate pattern was removed?
## Suggestions
Given that `SFSafariViewController` is a UIKit component, having `GIDSignIn` instantiate the `UIViewControllerRepresentable` and alongisde an overloaded `sharedInstance.signIn()` for SwiftUI users would vastly shorten the above example.
The other suggestion I have is maybe a timeline on SwiftUI support, or some documentation on existing workarounds, as most blog posts are written pre-v6, and instruct users to create delegates and such, which is no longer supported.
## Final Thoughts
I guess this brings me to my final question: is there SwiftUI support planned at all?
I'd be happy to write a sample project to catch up the Objective-C one currently in this repo, but without any official documentation for SwiftUI support it'd need a good chunk of review.
Contributor guide
Assessment
This issue has not been assessed yet.