10

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

Chris Prince
  • 7,288
  • 2
  • 48
  • 66
jwknz
  • 6,598
  • 16
  • 72
  • 115
  • Would upvote several times if I could. So relieved to not be the only one getting this issue on reshowing the login screen ! – Chris Neve Aug 03 '22 at 13:13

3 Answers3

22

Changing from:

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

To:

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

Made it work.

Tomer Domshlak
  • 397
  • 1
  • 8
2

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
Andy Hill
  • 136
  • 1
  • 11
1

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
Rev Archer
  • 27
  • 3