Skip to content

Using v6 in SwiftUI: .signIn() workaround and suggestions for SwiftUI support #49

@peterkos

Description

@peterkos

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:

- (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
  2. 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.

Tying it all together would be something like this:

// 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. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions