10. 编写你的第一个mutation
在本节中,你将编写第一个mutation以登录到后端。
mutation 用于更改您的服务器上的数据。这里登录mutation将根据您的邮箱地址创建会话。
注意:您登录到这个特定服务器的方式可能不同于您自己的服务器。登录通常由中间件,或者与GraphQL完全独立的层来处理,如OAuth。另外请注意,典型的身份验证流程通常需要密码,但在这篇教程中,任何人都可以用有效的电子邮箱地址预订飞行!
在Sandbox Explorer中原型化您的mutation
打开 您的Sandbox Explorer并点击加号以添加新标签页。接着,点击模式图标返回到查看您的模式,并选择"Mutation“以查看您的mutation列表:
向下滚动查看login
mutation:
点击右侧的播放按钮在探索器选项卡中打开该 mutation。当打开后,点击login
旁边的加号以添加操作:
请注意红色的错误指示 - 这是因为mutation返回的类型是User
,这不是一个叶类型:您需要选择mutation将返回用户哪个字段。在我们的情况下,我们只需要token
字段,因此通过点击其旁边的加号来添加它。
您还会注意到,尽管看起来没有默认值,但email
作为一个参数并没有自动添加:这是因为email
是String
类型——记得在GraphQL中,这意味着它是非必需的(尽管显然没有它您将无法走得太远)。
点击email
参数旁边的加号以添加该参数:
您还会注意到,沙箱资源管理器已将一个变量添加到您的“变量”部分以匹配登录电子邮件。
在您的mutation中点击提交操作按钮。您会看到,由于您为电子邮件地址发送了null
,登录返回的是null
:
现在,将查询变量部分中的null
替换成实际的电子邮件地址:
按下提交 操作按钮,这次你会得到实际响应:
接下来,复制操作,手动操作或使用三点菜单中的“复制操作”选项。
将突变添加到项目中
现在你的 mutaion 的工作正常,添加到项目中。在您的其他 GraphQL 文件旁边创建一个名为 Login.graphql
的文件,并将mutaion的内容粘贴进去:
mutation Login($email: String!) {login(email: $email) {token}}
注意:我们还将 email
变量标记为非空,通过在类型末尾添加 !
来实现,因为我们始终希望传递值给它。
在终端中运行代码生成以生成mutation的代码。
实现登录逻辑
首先,转到 LoginViewModel.swift
并添加以下 import
:
import Apolloimport RocketReserverAPI
接下来,代替 TODO
替换为以下代码:
Network.shared.apollo.perform(mutation: LoginMutation(email: email)) { [weak self] result indefer {self?.isSubmitEnabled = true}switch result {case .success(let graphQLResult):if let token = graphQLResult.data?.login?.token {// TODO - store token securelyself?.isPresented = false}if let errors = graphQLResult.errors {self?.appAlert = .errors(errors: errors)}case .failure(let error):self?.appAlert = .errors(errors: [error])}}
接下来,你需要储存由服务器返回的登录凭证。登录凭证始终应该存储在Keychain中,但是直接与之交互具有挑战性,所以您将使用已经作为Swift Package添加到本项目中的 KeychainSwift
库。
在 LoginViewModel.swift
的顶部添加以下 import
:
import KeychainSwift
现在,将摘取token后的 TODO - 将token安全存储
替换如下:
let keychain = KeychainSwift()keychain.set(token, forKey: LoginView.loginKeychainKey)
显示登录视图
接下来,我们需在预订/取消行程时检查用户是否已登录,以确定是否显示 LoginView
。
为此,前往 DetailViewModel.swift
,您会注意到 bookOrCancel()
方法中已经有了一些代码用于调用 isLoggedIn()
方法,如果返回 false,则会设置标志以显示登录视图。
func bookOrCancel() {guard self.isLoggedIn() else {isShowingLogin = truereturn}// TODO}
目前,isLoggedIn()
方法始终返回 false,所以现在让我们更新它,首先在 DetailViewModel.swift
中添加以下 import
:
import KeychainSwift
接下来,将 isLoggedIn()
方法的所有内容替换为以下内容:
private func isLoggedIn() -> Bool {let keychain = KeychainSwift()return keychain.get(LoginView.loginKeychainKey) != nil}
测试登录突变号
构建并运行应用程序,从列表中选择一个 启动 以进入 DetailView
。您应该看到点击 "立即预订!" 按钮,会显示登录视图;如果您使用此电子邮件 [email protected]
登录,随后点击 "立即预订!" 将不再显示登录视图。
在下一节中,您将学习如何 使用登录令牌验证您的操作。