在 SwiftUI 中调出 Google 登录屏幕

Posted

技术标签:

【中文标题】在 SwiftUI 中调出 Google 登录屏幕【英文标题】:Bringing up the Google Signin Screen in SwiftUI 【发布时间】:2020-04-21 12:42:48 【问题描述】:

我正在使用 Google 登录屏幕和 swiftUI,但我的日志中不断收到一堆我不太了解的消息 - 现在我可以使用这些日志,但我遇到的问题是我不能多次调用同一个函数...

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)
            
        
    

我收到的错误消息是:

2020-01-03 10:25:14.490522+1300 gsignin[34333:10734362] [AXRuntimeCommon] 此类“SwiftUI.AccessibilityNode”不是已知的可序列化元素,将其作为可访问性元素返回可能会导致崩溃

2020-01-03 10:25:14.789926+1300 gsignin[34333:10734511] [AXRuntimeCommon] 未知客户端:gsignin

2020-01-03 10:25:16.539753+1300 gsignin[34333:10734362] 键盘无法呈现视图控制器(试图呈现<SFAuthenticationViewController: 0x7f8a8a842200>

问题 1:我应该担心这个吗:[AXRuntimeCommon] Unknown client: gsignin

问题 2: 收到此消息后,登录屏幕第一次显示,但此后不再显示...Keyboard cannot present view controllers (attempted to present <SFAuthenticationViewController: 0x7f8a8a842200>)

如何修复这些消息?目前我没有任何进展。

PS。我不介意做更多的阅读/研究,但请保持友善 - 我是 swift 新手 :-D

【问题讨论】:

【参考方案1】:

iOS 15.0 更新:

UIApplication.shared.windowsios 15.0 中已弃用。 Xcode 建议将其替换为 UIWindowScene.windows。感谢https://***.com/a/58654791/,以下是我设法从UIWindowScene 获得rootViewController 的方法:

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

请注意,UIApplication.shared.keyWindow 在 iOS 13.0 中已弃用,但 UIWindowScene.keyWindow 未弃用。 UIApplication.shared.keyWindow 在具有多个场景的应用程序中是模棱两可的,UIWindowScene.keyWindow 不是。

或者,以下两种方法也可以:

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

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

【讨论】:

【参考方案2】:

更改自:

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

收件人:

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

让它工作。

【讨论】:

哇,谢谢!这对我有用。你能解释一下为什么会这样吗? 这会导致 iPad 出现问题吗? 对于其他构建在其他类型框架上但在 Objective-C 中有类似问题的人:[GIDSignIn sharedInstance].presentingViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController]; 完美运行!这是什么原因?对我来说,这个错误也是关于释放的。【参考方案3】:

我真的希望有人能告诉我我错了,但是 SwiftUI 还不支持你编写的谷歌登录代码的类型。因此,要使其正常工作,请使用以下结构:

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>) 

    

然后,放置线:

google()

在您希望按钮出现的 VStack 中。

此外,文档说您应该:

import Firebase

【讨论】:

以上是关于在 SwiftUI 中调出 Google 登录屏幕的主要内容,如果未能解决你的问题,请参考以下文章

FireBase 登录过程后导航到主屏幕(内容视图)。 (SwiftUI)

在按钮单击 SwiftUI 时导航到新屏幕

如何将我的登录屏幕链接到我的主屏幕 SwiftUI

点击注销时 SwiftUI 将应用程序重置为登录屏幕

swiftUI:登录完成后导航到主屏幕。通过按钮单击导航视图

如果新用户注册成功,如何打开一个屏幕,当现有用户使用 SwiftUI 成功登录时如何打开另一个屏幕?