欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

swiftui_使用SwiftUI进行Google登录

程序员文章站 2022-03-16 15:12:17
...

swiftui

Originally posted on my blog

最初发布在我的 博客上

总览 (Overview)

Google provides an easy SDK for integrating Google Sign-In with an iOS app with a helpful guide. However, the guide goes over code examples using UIKit, so I’ll be showing how to use Google Sign-In with SwiftUI and manage state (This is not meant to replace the guide, this just shows examples of using SwiftUI).

Google提供了一个简单的SDK,并提供了有用的指南 ,可将Google Sign-In与iOS应用集成。 但是,该指南介绍了使用UIKit的代码示例,因此,我将展示如何在SwiftUI中使用Google登录和管理状态(这并不意味着要取代指南,而只是显示使用SwiftUI的示例)。

安装 (Installation)

The guide has pages on setting up GoogleSignIn with your project. To summarize, you'll need to:

指南包含有关在您的项目中设置GoogleSignIn页面。 总结一下,您需要:

  • Add the GoogleSignIn package to your project with CocoaPods (pod 'GoogleSignIn').

    使用CocoaPods( pod 'GoogleSignIn' )将GoogleSignIn包添加到您的项目中。

  • Go to Google’s Developer Console to create a new project, then get your OAuth 2.0 Client ID credential.

    转到Google的开发者控制台创建一个新项目,然后获取OAuth 2.0客户端ID凭据。

  • Add an entry in “URL Types” under the “Info” tab on your project target in Xcode. The URL scheme is found in the developer console under “iOS URL scheme” (which is just your “Client ID” with the domains reversed). Adding the URL scheme allows the sign-in webpage to redirect back to your app.

    在Xcode项目目标的“信息”选项卡下的“ URL类型”中添加一个条目。 URL方案位于开发人员控制台的“ iOS URL方案”下(这是您的“客户端ID”,域相反)。 添加URL方案可以使登录网页重定向回您的应用。

Google代表 (Google Delegate)

Google recommends implementing the GIDSignInDelegate to your AppDelegate, but instead, we'll create a separate GoogleDelegate which will make it easier to manage SwiftUI state. GoogleDelegate will also implement ObservableObject and contain a published property—signedIn. The view that handles signing in can automatically update by observing the signedIn property.

Google建议将GIDSignInDelegate实施到您的AppDelegate ,但相反,我们将创建一个单独的GoogleDelegate ,这将使管理SwiftUI状态更加容易。 GoogleDelegate也将实现ObservableObject并包含一个已发布的属性signedIn 。 可以通过观察signedIn属性来自动更新用于处理登录的视图。

import GoogleSignInclass GoogleDelegate: NSObject, GIDSignInDelegate, ObservableObject {    @Published var signedIn: Bool = false    ...
}

Next, we’ll have to implement the sign(_:didSignInFor:withError:) method which is called when a user has signed in. The guide provides an example implementation, but we'll add a line that sets our signedIn property to true if the login was successful.

接下来,我们必须实现sign(_:didSignInFor:withError:)方法,该方法将在用户登录后调用。该指南提供了一个示例实现,但我们将添加一行将我们的signedIn属性设置为true如果登录成功。

func sign(_ signIn: GIDSignIn!, didSignInFor user: 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
} // If the previous `error` is null, then the sign-in was succesful
print("Successful sign-in!")
signedIn = true
}

Note: if you decide to handle an error a different way than just printing it, be sure to also check that the error isn’t GIDSignInErrorCode.canceled. If a user clicks the sign-in button then closes the sign-in page, sign(_:didSignInFor:withError:) will be called with a GIDSignInErrorCode.canceled error which you'll most likely want to ignore.

注意:如果您决定以不同于打印错误的其他方式来处理错误,请确保还检查该错误不是GIDSignInErrorCode.canceled 。 如果用户单击登录按钮然后关闭登录页面,则将使用GIDSignInErrorCode.canceled错误调用sign(_:didSignInFor:withError:) ,您很可能会忽略该错误。

应用和场景委托 (App & Scene Delegate)

Now that GoogleDelegate is complete, we'll need to add some more setup to our AppDelegate and SceneDelegate.

既然GoogleDelegate已经完成,我们将需要向AppDelegateSceneDelegate添加更多设置。

First, inside our AppDelegate's application(_:didFinishLaunchingWithOptions: (the application entry point), we'll setup our:

首先,在AppDelegateapplication(_:didFinishLaunchingWithOptions:应用程序入口点)内,我们将设置:

  • Client ID — The client ID is found inside the developer console.

    客户端ID-客户端ID可在开发人员控制台中找到。
  • Delegate — Our GoogleDelegate class.

    委托-我们的GoogleDelegate类。

  • Scopes — Any additional scopes your application needs to request.

    范围-您的应用程序需要请求的任何其他范围

// GIDSignIn's delegate is a weak property, so we have to define our GoogleDelegate outside the function to prevent it from being deallocated.
let googleDelegate = GoogleDelegate()func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GIDSignIn.sharedInstance().clientID = "...googleusercontent.com"
GIDSignIn.sharedInstance().delegate = googleDelegate
GIDSignIn.sharedInstance().scopes = Constants.GS.scopes return true
}

We also have to implement application(_:open:options:) which is called when the sign-in page redirects back to our app.

我们还必须实现application(_:open:options:) ,当登录页面重定向回我们的应用时会调用该应用。

func application(_ app: UIApplication, open url: URL, options [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}

Next, we have to add a few more things to the scene(_:willConnectTo:options:) method in SceneDelegate. First, we'll be setting our googleDelegate as an EnvironmentObject so that our views can easily access it. Second, we also need to set GIDSignIn.sharedInstance().presentingViewController. Normally, we would set the presentingViewController to whatever UIViewController has our sign-in view, but since we don't have any view controllers, we'll just set it to rootViewController.

接下来,我们必须在SceneDelegatescene(_:willConnectTo:options:)方法中添加更多内容。 首先,我们将googleDelegate设置为EnvironmentObject以便我们的视图可以轻松访问它。 其次,我们还需要设置GIDSignIn.sharedInstance().presentingViewController 。 通常,我们会将presentingViewController设置为具有我们的登录视图的UIViewController ,但是由于我们没有任何视图控制器,因此我们将其设置为rootViewController

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {    // Get the googleDelegate from AppDelegate
let googleDelegate = (UIApplication.shared.delegate as! AppDelegate).googleDelegate // Add googleDelegate as an environment object
let contentView = ContentView()
.environmentObject(googleDelegate) if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView) // Set presentingViewControll to rootViewController
GIDSignIn.sharedInstance().presentingViewController = window.rootViewController self.window = window
window.makeKeyAndVisible()
}
}

登录按钮 (The Sign-In Button)

Finally, with all the setup out of the way, we can create our sign-in page. We’ll design our page such that if the user isn’t signed in, we show a simple sign-in button. If the user is signed in, we’ll show their name and email along with a sign-out button. Note that the focus here is functionality, not a pretty UI.

最后,在完成所有设置之后,我们可以创建登录页面。 我们将设计页面,以便如果用户未登录,我们将显示一个简单的登录按钮。 如果用户已登录,我们将显示其姓名和电子邮件以及退出按钮。 请注意,这里的重点是功能,而不是漂亮的UI。

For the sign-in button, Google provides the GIDSignInButton class which is already has a standard Google-look and handles the tap action. Since the button is a UIControl, we need to wrap it in a UIViewRepresentable to use it in our SwiftUI body.

对于登录按钮,Google提供了GIDSignInButton类,该类已经具有标准的Google外观并可以处理轻GIDSignInButton操作。 由于按钮是UIControl ,因此我们需要将其包装在UIViewRepresentable ,以便在SwiftUI主体中使用它。

import GoogleSignIn
import SwiftUIstruct SignInButton: UIViewRepresentable { func makeUIView(context: Context) -> GIDSignInButton {
let button = GIDSignInButton()
// Customize button here
button.colorScheme = .light
return button
} func updateUIView(_ uiView: UIViewType, context: Context) {}
}struct ContentView: View { @EnvironmentObject var googleDelegate: GoogleDelegate var body: some View {
SignInButton()
}
}

Alternatively, you can create your own button and call GIDSignIn.sharedInstance().signIn() when it is tapped.

或者,您可以创建自己的按钮,并在点击该按钮时调用GIDSignIn.sharedInstance().signIn()

var body: some View {
Button(action: {
GIDSignIn.sharedInstance().signIn()
}) {
Text("Sign In")
}
}

Great, now our user can sign in. However, the whole point of GoogleDelegate was to update our view once the user is signed in, so let's show some of the user's information once they're signed in. The profile information can be found in GIDSignIn.sharedInstance().currentUser!.profile.

太好了,现在我们的用户可以登录了。但是, GoogleDelegate的全部目的是在用户登录后更新我们的视图,因此让我们在用户登录后显示一些用户信息。可以在以下位置找到个人资料信息GIDSignIn.sharedInstance().currentUser!.profile

We also need a sign-out button. When it’s pressed we call GIDSignIn.sharedInstance().signOut() and also set signedIn in our GoogleDelegate to false to show the sign-in button again.

我们还需要一个退出按钮。 按下时,我们调用GIDSignIn.sharedInstance().signOut() ,还将GoogleDelegate中的signedIn设置为false以再次显示登录按钮。

// To use if/else in our body, we need to wrap the view in a Group
var body: some View {
Group {
if googleDelegate.signedIn {
VStack {
Text(GIDSignIn.sharedInstance().currentUser!.profile.name)
Text(GIDSignIn.sharedInstance().currentUser!.profile.email)
Button(action: {
GIDSignIn.sharedInstance().signOut()
googleDelegate.signedIn = false
}) {
Text("Sign Out")
}
}
} else {
Button(action: {
GIDSignIn.sharedInstance().signIn()
}) {
Text("Sign In")
}
}
}
}

Now if we run our app, we’ll be greeted with a sign-in button. When pressed, the Google Sign-In modal will pop up. Note that if you requested sensitive scopes (scopes that can access personal information), you’ll see a warning that says “This app isn’t verified”. To get rid of this, you’ll need to get your app verified. But for testing, you can just press “Advanced” in the bottom left then “Go To *App* (unsafe)”.

现在,如果我们运行我们的应用程序,将会看到一个登录按钮。 按下时,将弹出Google登录模式。 请注意,如果您请求敏感范围(可以访问个人信息的范围),则会看到一条警告,指出“此应用未经过验证”。 要摆脱这种情况,您需要先验证您的应用程序。 但是对于测试,您只需按左下角的“高级”,然后按“转到* App *(不安全)”即可。

After you sign-in, the modal should disappear and the view should now show your name and email address, along with a sign-out button. Pressing sign-out will refresh the view and show the sign-in button once again.

登录后,模态窗口应消失,视图现在应显示您的姓名和电子邮件地址,以及退出按钮。 按退出将刷新视图并再次显示登录按钮。

swiftui_使用SwiftUI进行Google登录
Once the user is signed in, the view shows their name and email.
用户登录后,该视图将显示其姓名和电子邮件。

Finally, in order to automatically sign in our user when they close and reopen the app, we need to call GIDSignIn.sharedInstance().restorePreviousSignIn() when the user opens the sign-in page.

最后,为了在用户关闭并重新打开应用程序时自动登录我们,我们需要在用户打开登录页面时调用GIDSignIn.sharedInstance().restorePreviousSignIn()

var body: some View {
Group {
...
}
.onAppear {
GIDSignIn.sharedInstance().restorePreviousSignIn()
}
}

摘要 (Summary)

Using SwiftUI’s ObservableObject to manage state made it really easy for our view to automatically update when the user signs in or out. With UIKit you would have to manage messy NotificationCenter posts to update the UI when the user signs in or out.

使用SwiftUI的ObservableObject来管理状态,使用户登录或注销时视图的自动更新变得非常容易。 使用UIKit,您将必须管理混乱的NotificationCenter帖子以在用户登录或注销时更新UI。

Doing useful things with Google Sign-In such as making API calls or to authenticate the user to your own backend is out of the scope of this article, but Google provides many of their own guides.

使用Google登录进行有用的操作(例如进行API调用或对用户进行后端身份验证)不在本文的讨论范围之内,但是Google提供了许多自己的指南。

Originally posted on my blog

最初发布在我的 博客上

翻译自: https://medium.com/dev-genius/google-sign-in-with-swiftui-63f8e1deeae6

swiftui

相关标签: python