Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add google Sign-In with SwiftUI

I am trying to add google sign-in with swiftUI whith UIKitViewController, and for some reason I have difficulties showing the button does not appear in style

The signIn and the button works perfect but at some point the style of the button stopped appearing

I'm adding the button in a uikit viewcontroller, because I couldn't think of another way to handle the Google delegate

Here's the preview https://ibb.co/tYhx62b

//
//  GoogleSignInButtonView.swift
//
//  Created by Ivan Schaab on 11/09/2019.
//  Copyright © 2019 Ivan Schaab. All rights reserved.
//
import GoogleSignIn
import SwiftUI

struct GoogleSignInButtonView: View {

    @EnvironmentObject var lvm: LoginViewModel

    var body: some View {
        HStack {
            Spacer()
            GoogleButtonViewControllerRepresentable { (token, user) in
                // Google Login Success
                // Now do Backend Validations
                self.lvm.loginOauth(token: token, user: user)
            }
            Spacer()
        }.frame(alignment: .center)
    }
}

class GoogleButtonUIKitViewController: UIViewController {

    var signInButton = GIDSignInButton()

    override func viewDidLoad() {
        super.viewDidLoad()

        GIDSignIn.sharedInstance().clientID = Constants.GOOGLE_CLIENT_ID
        self.view.addSubview(signInButton)

        GIDSignIn.sharedInstance()?.presentingViewController = self

        // Automatically sign in the user.
        GIDSignIn.sharedInstance()?.restorePreviousSignIn()
    }
}

struct GoogleButtonViewControllerRepresentable: UIViewControllerRepresentable
{
    let vc = GoogleButtonUIKitViewController()
    var googleResponse: (String, User) -> Void

    func makeUIViewController(context: Context) -> GoogleButtonUIKitViewController {
        return vc
    }
    func updateUIViewController(_ uiViewController: GoogleButtonUIKitViewController, context: Context) {}
    func makeCoordinator() -> Coordinator {
        Coordinator(vc: vc, googleResponse: googleResponse)
    }

    static func dismantleUIViewController(_ uiViewController: GoogleButtonUIKitViewController, coordinator: GoogleButtonViewControllerRepresentable.Coordinator) {
        print("DISMANTLE")
    }

    class Coordinator: NSObject, GIDSignInDelegate  {
        var foo: (String, User) -> Void
        init(vc: GoogleButtonUIKitViewController, googleResponse: @escaping (String, User) -> Void) {
            self.foo = googleResponse
            super.init()
            GIDSignIn.sharedInstance()?.delegate = self
        }

        func sign(_ signIn: GIDSignIn!, didSignInFor googleUser: GIDGoogleUser!, withError error: Error!) {
            if let error = error {
                if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
                    print("The user has not signed in before or they have since signed out.")
                } else {
                    print("\(error.localizedDescription)")
                }
                return
            }
//            let userId = googleUser.userID                  // For client-side use only!
            let idToken = googleUser.authentication.idToken // Safe to send to the server
            let email = googleUser.profile.email

            if googleUser.profile.hasImage{
                let imageUrl = googleUser.profile.imageURL(withDimension: 120)
                print(" image url: ", imageUrl?.absoluteString ?? "NO URL")
            }

            let user : User = User(id: 1, name: googleUser.profile.givenName, surname: googleUser.profile.familyName, imgName: ""  , email: googleUser.profile.email)

            print("email: ",email ?? "NO EMAIL")

            foo(idToken! , user)
        }
    }
}



#if DEBUG
struct SomeRepView_Previews: PreviewProvider {
    static var previews: some View {
        GoogleSignInButtonView().environmentObject(LoginViewModel())
    }
}
#endif
like image 375
Ivan Schaab Avatar asked Sep 13 '19 13:09

Ivan Schaab


People also ask

How do I add a login to Apple SwiftUI?

Go to Project Navigator -> Select the Target -> Click the 'Signing & Capabilities' tab. -> click Capability and add the Sign In with Apple capability. Go to the Developer Portal -> Create a New Bundle ID or Select Existing Bundle ID and under the Capabilities select the checkbox for 'Sign In with Apple'.

How do I sign into Google on iOS?

On your iPhone or iPad, open the Safari app. Go to www.google.com. Tap your profile image or Sign in. Follow the sign-in steps.

How do I log into Google firebase Swift?

If you haven't yet connected your app to your Firebase project, do so from the Firebase console. Enable Google as a sign-in method in the Firebase console: In the Firebase console, open the Auth section. On the Sign in method tab, enable the Google sign-in method and click Save.


3 Answers

This is a part of my code where I implement Facebook and Google login, using any button I hope it helps you

import SwiftUI
import GoogleSignIn
import FBSDKLoginKit

var body: some View {
    LoadingView(isShowing: .constant(loading)) {
        NavigationView {
            ScrollView {
                VStack {

                    Text("Or Login with").font(.footnote)

                    HStack {
                        Button(action: self.logginFb, label: {
                            Image("ic_facebook").foregroundColor(Color.white).frame(width: 20, height: 20)
                        })
                                .padding(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
                                .background(Color("facebook"))
                                .cornerRadius(8.0)

                        Button(action: self.socialLogin.attemptLoginGoogle, label: {
                            Image("ic_google").frame(width: 20, height: 20)
                        })
                                .padding(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
                                .background(Color.white)
                                .cornerRadius(8.0)
                                .shadow(radius: 4.0)


                    }.padding()
                }.padding(.all, 32)
            }.navigationBarTitle(Text("Login"))
        }
    }
}

    func logginFb() {
        socialLogin.attemptLoginFb(completion: { result, error in

        })
    }


struct SocialLogin: UIViewRepresentable {

    func makeUIView(context: UIViewRepresentableContext<SocialLogin>) -> UIView {
        return UIView()
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<SocialLogin>) {
    }

    func attemptLoginGoogle() {
        GIDSignIn.sharedInstance()?.presentingViewController = UIApplication.shared.windows.last?.rootViewController
        GIDSignIn.sharedInstance()?.signIn()
    }

    func attemptLoginFb(completion: @escaping (_ result: FBSDKLoginManagerLoginResult?, _ error: Error?) -> Void) {
        let fbLoginManager: FBSDKLoginManager = FBSDKLoginManager()
        fbLoginManager.logOut()
        fbLoginManager.logIn(withReadPermissions: ["email"], from: UIApplication.shared.windows.last?.rootViewController) { (result, error) -> Void in
            completion(result, error)
        }
    }

}

struct LoginView_Previews: PreviewProvider {
    static var previews: some View {
        LoginView()
    }
}

The configuration of google and facebook in AppDelegate is the same as its documentation.

Now with swiftUI it is not necessary to use the default buttons that you give us.

Google and Facebook custom buttons Google and Facebook custom buttons

like image 67
yOshi Avatar answered Oct 23 '22 15:10

yOshi


Note for SwiftUI 2.0 lifecycle: there is no standard AppDelegate so you also need to add an adapter in main App file:

@main
struct ExampleApp: App {
    @UIApplicationDelegateAdaptor(ExampleAppDelegate.self) var appDelegate

and prepare the Delegate in a separate file:

//No @UIApplicationMain
class ExampleAppDelegate: NSObject, UIApplicationDelegate, GIDSignInDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    GIDSignIn.sharedInstance().clientID = "YOUR CLINET ID"
    GIDSignIn.sharedInstance().delegate = self

    return true
  }

...
like image 30
Konrad Leszczyński Avatar answered Oct 23 '22 13:10

Konrad Leszczyński


With the latest SwiftUI, you can setup the GIDSignInDelegate within your AppDelegate and ensure that it conforms to all methods. Then, within your SceneDelegate, when setting up the window, you can drop this line in to setup the presenting view controller:

GIDSignIn.sharedInstance()?.presentingViewController = window.rootViewController.

Lastly, when creating your button, set the action or tap gesture to call GIDSignIn.sharedInstance().signIn() and you should be good to go!

like image 1
Kyle Beard Avatar answered Oct 23 '22 14:10

Kyle Beard