query TodoQuery {
listTodos {
items {
completed
该GraphQL
查询仅通过指定其关注的字段来访问所需的数据。 您将此查询发送到服务器,并且服务器使用与您的查询匹配的数据结构进行响应。 以这种方式添加和删除字段将需要在使用REST
时对API进行更改,而在这里,您只需在应用程序内部更改查询,而无需完全修改服务器。
2. GraphQL with AWS AppSync
AWS AppSync
可以完成后端Web服务的所有繁重工作。 它充当GraphQL
和其他AWS
服务(例如数据存储,缓存和实时更新)之间的桥梁。
AppSync
为您的项目提供了一个仪表板,您可以在其中查看和查询数据,以及通过自定义功能添加自定义功能。
您的应用将在后台通过GraphQL
与AppSync
进行通信; 但是,您将使用AppSync iOS
框架来消除很多这种复杂性。 完成一些配置后,您只会以一种类型安全的方式谈论您的后端。
Installing the Amplify Framework
您将从安装项目依赖项开始。 您可能已经安装了其中的一些(或全部)。 在这种情况下,您可以跳到相关部分。
1. Installing npm
Node Package Manager (npm)
是一个软件包管理器和CLI (command line interface)
,用于管理Node.js
软件包。 在此项目中,您将使用npm
安装Amplify CLI
。
如果不确定是否已安装npm
,请打开“终端”并键入npm -v
,然后按Enter
。 如果已安装,则应该在“终端”窗口中看到打印的版本号。
npm
与Node.js
一起安装。 要同时安装Node.js
和npm
,请导航到node.js website网站,然后单击标有LTS
的下载链接。 在撰写本文时,当前的LTS
版本是14.15.1 LTS
。
下载完成后,打开.pkg
文件,您应该看到以下内容:
单击继续,然后按照步骤进行。 安装完成后,重新启动Terminal
并键入npm -v
并按Enter。 现在,您应该看到版本号。
2. Installing Amplify CLI
通过命令行安装Amplify
。 在终端内,键入以下内容,然后按Enter。
sudo npm install -g @aws-amplify/cli
根据需要输入系统密码。 npm会在终端窗口中看到很多活动。 安装Amplify
后,您应该会看到类似以下的内容:
----------------------------------------
Successfully installed the Amplify CLI
----------------------------------------
此过程完成后,输入以下命令,然后按Enter
:
amplify configure
该命令将在新的浏览器窗口中打开AWS
登录页面。 如果您还没有AWS
帐户,则需要先注册一个帐户,然后才能完成此步骤。 注册非常容易。 有关如何执行此操作的说明,请参阅 at the AWS knowledge center。 完成后,请务必从此开始继续本教程。
在浏览器窗口中登录到您的AWS
账户。 登录后,返回“终端”窗口,然后按Enter
。
接下来,您需要指定您的区域。 使用箭头键选择最能代表您的位置的区域,然后按Enter。
接下来输入新用户的用户名,然后按Enter
。 这可以是您想要的任何东西。
这会将您定向到AWS
控制台以完成设置。 使用底部的按钮单击整个设置过程,并确保在权限屏幕上选中了AdministratorAccess
。
返回“终端”窗口,然后按Enter
。
当终端提示时,输入您的Access Key ID
和Secret Access Key
。
最后,在要求输入Profile Name
时,最后一次按Enter
键。 这会将您的配置文件设置为default
。
3. Installing CocoaPods
您将使用CocoaPods
将AppSync
框架添加到您的项目中。 如果您不熟悉CocoaPods
,可以在我们的 CocoaPods Tutorial for Swift教程中了解
CocoaPods
通过Ruby
安装,而Ruby
已经安装在Mac
上。 打开终端,键入以下命令,然后按Enter。
sudo gem install cocoapods
短暂的延迟后,您应该在终端窗口中看到Successfully installed cocoapods-VERSION
。
Adding Amplify to the Project
现在你已经设置好了依赖项,你可以继续在Xcode中设置项目了。确保你在下一步关闭Xcode
,是的,你没听错!
打开一个终端屏幕,并使用cd
导航到starter
项目目录。然后,在终端窗口中输入以下内容:
pod init
命令执行完毕后,您将注意到项目目录中出现了一个名为Podfile
的新文件。在一个文本编辑器中打开Podfile
,添加如下# Pods for RazeList
:
pod 'Amplify'
pod 'Amplify/Tools'
pod 'AmplifyPlugins/AWSAPIPlugin'
pod 'AmplifyPlugins/AWSDataStorePlugin'
回到终端窗口并输入以下命令:
pod install
几秒钟后,您应该看到以下消息:
Pod installation complete! There are 4 dependencies from the Podfile and 12 total pods installed.
瞧!就像这样,您的包已经安装并包含在您的项目中。
在Finder
中打开项目目录,您将注意到现在有一个CocoaPods
创建的名为RazeList.xcworkspace
的工作空间文件。双击这个文件,你的项目就会在Xcode
中打开。从现在开始使用这个文件来打开你的项目,而不是RazeList.xcodeproj
,因为它包含所有需要的依赖项。
1. Adding AppSync Script
你快过终点线了。在编写任何代码之前,你需要做的最后一件事是在Xcode的Build Phases
选项卡中添加一个Run Script
。这个脚本执行一些需要在项目中使用AppSync
的任务。
在Xcode
中选择RazeList
项目。在project explorer
中,单击Build Phases
。单击+按钮并选择New Run Script Phase
。
"${PODS_ROOT}/AmplifyTools/amplify-tools.sh"
现在构建并运行项目。这次的构建时间会稍长一些,因为Xcode
将运行脚本(Run Script)
作为构建过程的一部分执行。当构建完成时,你的项目中会有更多的文件;您将在下一节中使用这些。在进入下一阶段之前等待项目构建是很重要的。
2. Initializing Amplify
一旦构建过程完成,您将需要在项目中初始化amplify
。当您在项目导航器中看到一个名为AmplifyConfig
的新文件夹时,您就会知道构建已经完成了它的工作。
确保您在终端的项目目录中,并输入以下命令:
amplify init
根据界面提示输入如下信息:
? Enter a name for the environment
Press Enter
? Choose your default editor
? Do you want to use an AWS profile?
? Please choose the profile you want to use
Press Enter for default
在同一个终端窗口中,输入以下命令,然后按Enter
。
amplify add api
根据界面提示输入如下信息。其他步骤按enter
,使用默认设置。
? Please select from one of the below mentioned services:
GraphQL
? Provide API name:
Press Enter to set this to your directory name.
接下来输入以下命令。
amplify push
根据界面提示输入如下信息。
? Are you sure you want to continue?
? Do you want to generate code for your newly created GraphQL API
这可能看起来有很多设置,但Amplify
已经为您做了很多。您已经创建了一个用户,设置了一个应用程序并将其添加到AWS
仪表板,创建了一个GraphQL API
并将其发布到AWS
。一切都准备好了!
Creating Models Using GraphQL
在处理后端服务时,您可能希望将数据类型表示为模型。Amplify
让你省去了自己打印它们的麻烦。那不是很好吗?
但是,您仍然需要告诉Amplify
要生成什么,这将使用GraphQL
完成!
打开AmplifyConfig
组内的schema.graphql
。
替换该文件的内容如下:
type Todo @model {
id: ID!
name: String!
description: String
completed: Boolean!
接下来,打开同一个目录中的amplifytools.xcconfig
。将push
和modelgen
更改为true
。
构建并运行项目。构建完成后,项目导航器中会有一个名为AmplifyModels
的新目录。在配置中更改上面的行告诉Amplify
从GraphQL schema
模式为您生成模型文件,并更新AWS
上的配置。扩大AmplifyModels
,看看周围。您将看到Todo.swift
包含您的模型和一些帮助文件。
1. Using Amplify in the App
在左侧的项目导航器中,打开AppMain.swift
并添加以下导入:
import Amplify
import AmplifyPlugins
在AppDelegate
类中,在application(_:didFinishLaunchingWithOptions:)
函数返回true
之前添加以下代码:
let apiPlugin = AWSAPIPlugin(modelRegistration: AmplifyModels())
let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels())
try Amplify.add(plugin: apiPlugin)
try Amplify.add(plugin: dataStorePlugin)
try Amplify.configure()
print("Initialized Amplify")
} catch {
print("Could not initialize Amplify: \(error)")
构建并运行项目。
Building the To Do List UI
安装了库,设置了CocoaPods
并生成了模型之后,就该使RazeList
变得栩栩如生了。
本教程的某些SwiftUI
编码已为您完成,但您仍需要构建主要任务清单。 这就是本节中要执行的操作。
1. Adding Rows to the To Do List
首先定义行。 右键单击Views
组,然后选择New File
选项。 选择SwiftUI View
,然后单击Next
。 将文件命名为TodoRowView.swift
并创建它。
打开该文件,然后在TodoRowView
声明下方添加以下内容。
let todoItem: Todo
let onToggleCompleted: (Todo) -> Void
待办事项行定义了两个要求。
1) 用于渲染的Todo
模型。
2) 当用户切换完成状态时调用的闭包。
这将导致错误,因为预览没有传递这些依赖项。 用以下内容替换TodoRowView_Previews
的全部内容:
struct TodoRowView_Previews: PreviewProvider {
static var previews: some View {
TodoRowView(
todoItem: Todo(
id: UUID().uuidString,
name: "Build this cool app",
description: "I need to finish building this awesome todo list app :]",
completed: false)) { _ in }
接下来,您将定义一个方法,当用户切换待办事项时。 将以下方法添加到TodoRowView
中:
func toggleCompleted() {
withAnimation {
onToggleCompleted(todoItem)
此函数仅将onToggle Completed
封装在动画块中,该动画块将使各节之间的行移动具有动画效果。
接下来,将整个body
替换为以下内容:
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 10) {
Button(action: { onToggleCompleted(todoItem) }) {
Image(systemName: todoItem.completed ? "checkmark.square" : "square")
.imageScale(.large)
.foregroundColor(todoItem.completed ? .pink : .primary)
Text(todoItem.name)
.font(.system(size: 18, weight: .semibold))
if let description = todoItem.description {
Text(description)
.font(.system(size: 14, weight: .medium))
.padding(.leading, 32)
.padding(.trailing, 10)
.foregroundColor(.gray)
上面的代码是这样的:
1) 定义一个VStack
容器。
2) 定义一个HStack
,其中包含带有复选框图像的按钮。 根据待执行模型的completed
属性的状态来选择是否选中该图像。 点击按钮将调用onToggleCompleted(_ :)
。
3) 堆栈stack
中的第二项是包含要执行的操作的名称的Text
视图。
4) 如果待办事项包含描述,请在Text
视图中呈现它。
2. Setting up Your Data
打开TodoListViewModel.swift
。 在类实现内添加以下代码:
@Published var todos: [Todo] = []
@Published var completedTodos: [Todo] = []
TodoListViewModel
符合ObservableObject
。 遵循此协议,允许对象在状态更改时发布更新。 使用@Published
属性包装器告诉对象通过其发布者将更改广播给正在收听的任何人。 当对象更新时,SwiftUI
使用它来重绘UI。
如果您想了解有关ObservableObject
的更多信息,请查看Combine: Asynchronous Programming with Swift。
接下来,打开TodoListView.swift
并在视图实现中添加以下代码:
@ObservedObject var viewModel = TodoListViewModel()
在这里,您将使用@ObservedObject
属性包装器创建对TodoListViewModel
的引用。 以这种方式创建属性会告诉SwiftUI
您关心该对象的状态,并且它应该响应更改。
3. Adding Sections
接下来,您将定义两个部分,一个用于待办事项,一个用于完成待办事项。 一般来说,您希望保持body
轻点。 考虑到这一点,您将把这两个部分定义为计算属性。
将第一部分添加到TodoListView
中:
var todoSection: some View {
Group {
if viewModel.todos.isEmpty {
Text("Nothing to do!")
} else {
ForEach(viewModel.todos, id: \.id) { todo in
TodoRowView(todoItem: todo) { todo in
withAnimation {
// Toggle complete
.padding(.vertical, 6)
.onDelete(perform: viewModel.deleteTodos)
一点一点地:
1) 您无法选择返回Text
视图或ForEach
视图,因此它们被包装在Group
中。
2) 如果列表中没有待办事项,请返回一个反映此情况的Text
视图。
3) 如果有待办事项,请遍历每个步骤以在ForEach
中执行。
4) 对于列表中的每个操作,生成一个TodoRowView
并传递当前操作。
接下来,您将完成已完成的任务。 在todoSection
属性下方,添加以下内容:
var completedTodoSection: some View {
Group {
if viewModel.completedTodos.isEmpty {
Text("Completed Tasks Appear Here")
} else {
ForEach(viewModel.completedTodos, id: \.id) { todo in
TodoRowView(todoItem: todo) { todo in
withAnimation {
// Toggle complete
.padding(.vertical, 6)
.onDelete(perform: viewModel.deleteCompletedTodos)
唯一的区别是您已将对viewModel.todos
的引用替换为viewModel.completedTodos
。
现在,您已经定义了两个列表部分,现在该看看它们的实际效果了!
将body
内容替换为以下内容:
List {
Section(header: Text("Todo")) {
todoSection
Section(header: Text("Completed")) {
completedTodoSection
.listStyle(GroupedListStyle())
上面的代码执行以下操作:
1) 创建一个列表以包含您先前创建的部分。
2) 将“待办事项”部分嵌入Section
视图中。
3) 将完成的待办事项部分嵌入到Section
视图中。
4) 为列表提供分组样式。 这将分隔各节并应用一些默认样式。
构建并运行以查看结果。
您终于摆脱了hello world
应用! 真好
4. Adding a To Do
在本部分的最后部分,您将集成“添加待办事项”屏幕。 用户界面已经构建,因此这是一个相当简单的步骤。
转到TodoListView.swift
并在视图实现内添加一个新属性:
@State var addNewTodoPresented: Bool = false
这将负责呈现和关闭添加视图。
在body
的底部,.listStyle(GroupedListStyle())
之后的行上,添加以下视图修饰符:
.navigationBarItems(
trailing: Button(action: { addNewTodoPresented.toggle() }) {
Image(systemName: "plus")
.imageScale(.large)
.sheet(isPresented: $addNewTodoPresented) {
AddTodoView { name, description in
// add todo
addNewTodoPresented.toggle()
这看起来有点复杂,但实际上相当简单:
1) navigationBarItems(trailing :)
视图修饰符将导航项添加到封闭的NavigationView
的导航栏中。 您在此处添加了一个按钮,点击该按钮即可切换addNewTodoPresented
。
2) 当isPresented
状态为true
时,sheet(isPresented:content :)
视图修饰符将显示一个模型。 闭包返回要显示的视图。 在这种情况下,您将返回AddTodoView
。
构建并运行以查看结果。
Creating and Editing To Dos
所有人都已设置完毕,并具有正常运行的用户界面。 您需要做的最后一件事就是将所有东西连接起来!
打开TodoListViewModel.swift
并添加一个新的导入。
import Amplify
1. Adding To Dos
接下来,添加以下方法:
func createTodo(name: String, description: String?) {
let item = Todo(name: name, description: description, completed: false)
todos.append(item)
Amplify.DataStore.save(item) { result in
switch result {
case .success(let savedItem):
print("Saved item: \(savedItem.name)")
case .failure(let error):
print("Could not save item with error: \(error)")
使用前面步骤中的所有配置,这就是将数据保存到本地和云数据存储中所需要的全部。 这是正在发生的事情:
1) 使用传入的变量创建新的待办事项。
2) 将其添加到本地待办事项todos
数组。
3) 使用Amplify
框架,将to do
添加到您的数据存储中。
接下来打开TodoListView.swift
,然后向下滚动到body
末尾的.sheet
修改器。 在addNewTodoPresented.toggle()
上方一行的闭包中,添加对createTodo(name:description :)
函数的调用。
viewModel.createTodo(name: name, description: description)
您现在可以保存待办事项,但是除非您可以加载它们,否则这样做是没有用的!
返回TodoListViewModel.swift
,将loadToDos()
替换为以下内容。
func loadToDos() {
Amplify.DataStore.query(Todo.self) { result in
switch result {
case .success(let todos):
self.todos = todos.filter { !$0.completed }
completedTodos = todos.filter { $0.completed }
case .failure(let error):
print("Could not query DataStore: \(error)")
现在,在TodoListView.swift
中,在.sheet
下添加一个新的视图修改器。
.onAppear {
viewModel.loadToDos()
构建并运行项目以添加您的第一个待办事项!
2. Completing To Dos
到目前为止,该应用程序非常适合向您显示您需要做的事情-但并不擅长让您完成这些任务。
打开TodoListViewModel
。 滚动到底部,然后在loadTodos()
之后添加以下新方法:
func toggleComplete(_ todo: Todo) {
var updatedTodo = todo
updatedTodo.completed.toggle()
Amplify.DataStore.save(updatedTodo) { result in
switch result {
case .success(let savedTodo):
print("Updated item: \(savedTodo.name )")
case .failure(let error):
print("Could not update data with error: \(error)")
if updatedTodo.completed {
if let index = todos.firstIndex(where: { $0.id == todo.id }) {
todos.remove(at: index)
completedTodos.insert(updatedTodo, at: 0)
} else {
if let index = completedTodos.firstIndex(where: { $0.id == todo.id }) {
completedTodos.remove(at: index)
todos.insert(updatedTodo, at: 0)
好的,这是相当一部分代码。 它的作用是:
1) 制作一个可变的副本即可进行修改,然后切换完成的值。
2) 使用Amplify
,将的操作保存回您的数据存储中。
3) 如果待办事项已完成,请将其从待办事项todos
中删除并将其添加到completedTodos
。
4) 如果待办事项尚未完成,请将其从completedTodos
中删除并将其添加到待办事项中。
打开TodoListView.swift
并导航到顶部的两个属性。 在todoSection
和completedTodoSection
中,您会注意到两个占位符注释// Toggle complete
。 用以下两个地方替换该注释:
viewModel.toggleComplete(todo)
构建并运行该应用程序。 现在,您可以轻按任一列表中的每个待办事项,并以很酷的动画更改完成状态!
3. Deleting To Dos
您需要添加的最后一件事是删除行的方法。 UI中已经存在“滑动删除”功能,因此您只需将其连接起来即可。
打开TodoListViewModel.swift
,您会在顶部注意到三种删除方法。 这些将充当帮助方法,以从其各自的列表中删除待办事项。
添加以下方法:
func delete(todo: Todo) {
Amplify.DataStore.delete(todo) { result in
switch result {
case .success:
print("Deleted item: \(todo.name)")
case .failure(let error):
print("Could not update data with error: \(error)")
此方法通过从Amplify
框架调用delete(_ :)
从数据存储中删除模型。
接下来,将以下三种删除方法替换为:
func deleteItems(at offsets: IndexSet, from todoList: inout [Todo]) {
for index in offsets {
let todo = todoList[index]
delete(todo: todo)
todoList.remove(atOffsets: offsets)
func deleteTodos(at offsets: IndexSet) {
deleteItems(at: offsets, from: &todos)
func deleteCompletedTodos(at offsets: IndexSet) {
deleteItems(at: offsets, from: &completedTodos)
这是您所做的:
1) 第一个删除方法调用刚添加的delete(at:from :)
。
2) 此方法使用todos
数组路由要删除的调用。
3) 此方法使用completedTodos
数组路由要删除的呼叫。
构建并运行项目。 您现在可以滑动以删除待办事项!
现在,您有一个待办事项列表,可用于添加,编辑和删除待办事项。 它可以脱机工作,并与AWS
后端保持同步。
现在,您已经知道在iOS应用中集成和使用AppSync
和Amplify
的基础知识-但是还有很多东西要学习! GraphQL
可以做的比您在这里介绍的要多得多。
当您准备好使用AWS
和Amplify
进行下一步时,请查看 Using AWS as a Back End: Authentication & API 和 Using AWS as a Back End: The Data Store API。
查看我们的教程GraphQL Using the Apollo Framework: Getting Started,以查看更多实际示例。 您也可以在GraphQL
官方网站official GraphQL website.上了解有关GraphQL
的更多信息。
您还应该查看亚马逊为进一步学习而制作的官方AWS AppSync教程official AWS AppSync tutorials。
本篇主要讲述了基于基于SwiftUI
的AWS AppSync
框架的使用,感兴趣的给个赞或者关注~~~