简体   繁体   中英

Bringing up the Google Signin Screen in SwiftUI

I am playing around with the Google sign in screen and swiftUI, but I keep getting a bunch of messages in my logs that I don't really understand - now the logs I can live with, but the problem I am having is that I can't call the same function multiple times...

import SwiftUI
import GoogleSignIn

class GoogleStuff: UIViewController, GIDSignInDelegate, ObservableObject {
    
    var googleSignIn = GIDSignIn.sharedInstance()
    var googleId = ""
    var googleIdToken = ""
    var googleFirstName = ""
    var googleLastName = ""
    var googleEmail = ""
    var googleProfileURL = ""
    
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        
        guard user != nil else {
            print("Uh oh. The user cancelled the Google login.")
            return
        }
        
        print("TOKEN => \(user.authentication.idToken!)")

        
    }
    
    func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
        
        guard user != nil else {
            print("Uh oh. The user cancelled the Google login.")
            return
        }
        
        print("TOKEN => \(user.authentication.idToken!)")
        
    }
}

struct ContentView: View {
    
    let googleSignIn = GIDSignIn.sharedInstance()
    
    @ObservedObject var myGoogle = GoogleStuff()
    
    @State private var signedIn = false
    @State private var buttonLabel = "Google Sign In"
            
    var body: some View {
        VStack {
                             
            Button(action: {
                self.signedIn.toggle()
                self.buttonLabel = self.signedIn ? "Google Sign In" : "Google Sign Out"
                
                self.googleSignIn?.presentingViewController = UIApplication.shared.windows.last?.rootViewController
                self.googleSignIn?.clientID = "MY_TOKEN_GOES_HERE" //It is just a playground for now
                self.googleSignIn?.delegate = self.myGoogle
                self.googleSignIn?.signIn()
            }) {
                HStack {
                    Image("GLogo")
                        .resizable()
                        .frame(width: 40, height: 40, alignment: .center)
                    Text(buttonLabel)
                    .foregroundColor(.blue)
                    .font(.title)
                    .font(.custom("Roboto-Thin", size: 20))
                }
                .padding()
                .border(Color.black, width: 3)
            }
        }
    }
}

The error messages I am getting are:

2020-01-03 10:25:14.490522+1300 gsignin[34333:10734362] [AXRuntimeCommon] This class 'SwiftUI.AccessibilityNode' is not a known serializable element and returning it as an accessibility element may lead to crashes

2020-01-03 10:25:14.789926+1300 gsignin[34333:10734511] [AXRuntimeCommon] Unknown client: gsignin

2020-01-03 10:25:16.539753+1300 gsignin[34333:10734362] Keyboard cannot present view controllers (attempted to present <SFAuthenticationViewController: 0x7f8a8a842200> )

Question 1: Should I be concerned about this: [AXRuntimeCommon] Unknown client: gsignin

Question 2: Once I get this messages, the login screen shows up the first time, but not any time after that... Keyboard cannot present view controllers (attempted to present <SFAuthenticationViewController: 0x7f8a8a842200>)

How can I fix these messages? At the moment I am not getting anywhere.

PS. I don't mind doing some more reading / research, but please be nice - I am new to swift :-D

Changing from:

self.googleSignIn?.presentingViewController = 
UIApplication.shared.windows.last?.rootViewController

To:

self.googleSignIn?.presentingViewController = 
UIApplication.shared.windows.first?.rootViewController

Made it work.

I really hope that someone can tell me I'm wrong about this, but SwiftUI does not yet support the type of Google Sign-in code you wrote. So, to make it work, use this structure:

struct google : UIViewRepresentable {

    func makeUIView(context: UIViewRepresentableContext<google>) -> GIDSignInButton {

        let button = GIDSignInButton()
        GIDSignIn.sharedInstance()?.presentingViewController = UIApplication.shared.windows.last?.rootViewController
        return button
    }

    func updateUIView(_ uiView: GIDSignInButton, context: UIViewRepresentableContext<google>) {

    }
}

Then, place the line:

google()

in your VStack where you want the button to appear.

Also, the documentation says you should:

import Firebase

Update for iOS 15.0 :

UIApplication.shared.windows is deprecated in iOS 15.0. Xcode recommends replacing it with UIWindowScene.windows . Here's how I managed to obtain a rootViewController from UIWindowScene thanks to https://stackoverflow.com/a/58654791/ :

self.googleSignIn?.presentingViewController = 
(UIApplication.shared.connectedScenes.first as? UIWindowScene)?.keyWindow?.rootViewController

Note that UIApplication.shared.keyWindow was deprecated in iOS 13.0, but not UIWindowScene.keyWindow . Whereas UIApplication.shared.keyWindow is ambiguous in apps with multiple scenes, UIWindowScene.keyWindow is not.

Alternatively both of the following also work:

self.googleSignIn?.presentingViewController = 
(UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.last?.rootViewController

and

self.googleSignIn?.presentingViewController = 
(UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first?.rootViewController

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM