版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2021.01.12 星期二 |
前言
今天翻閱蘋果的API文檔,發(fā)現(xiàn)多了一個(gè)框架SwiftUI,這里我們就一起來看一下這個(gè)框架哆姻。感興趣的看下面幾篇文章芙沥。
1. SwiftUI框架詳細(xì)解析 (一) —— 基本概覽(一)
2. SwiftUI框架詳細(xì)解析 (二) —— 基于SwiftUI的閃屏頁的創(chuàng)建(一)
3. SwiftUI框架詳細(xì)解析 (三) —— 基于SwiftUI的閃屏頁的創(chuàng)建(二)
4. SwiftUI框架詳細(xì)解析 (四) —— 使用SwiftUI進(jìn)行蘋果登錄(一)
5. SwiftUI框架詳細(xì)解析 (五) —— 使用SwiftUI進(jìn)行蘋果登錄(二)
6. SwiftUI框架詳細(xì)解析 (六) —— 基于SwiftUI的導(dǎo)航的實(shí)現(xiàn)(一)
7. SwiftUI框架詳細(xì)解析 (七) —— 基于SwiftUI的導(dǎo)航的實(shí)現(xiàn)(二)
8. SwiftUI框架詳細(xì)解析 (八) —— 基于SwiftUI的動(dòng)畫的實(shí)現(xiàn)(一)
9. SwiftUI框架詳細(xì)解析 (九) —— 基于SwiftUI的動(dòng)畫的實(shí)現(xiàn)(二)
10. SwiftUI框架詳細(xì)解析 (十) —— 基于SwiftUI構(gòu)建各種自定義圖表(一)
11. SwiftUI框架詳細(xì)解析 (十一) —— 基于SwiftUI構(gòu)建各種自定義圖表(二)
12. SwiftUI框架詳細(xì)解析 (十二) —— 基于SwiftUI創(chuàng)建Mind-Map UI(一)
13. SwiftUI框架詳細(xì)解析 (十三) —— 基于SwiftUI創(chuàng)建Mind-Map UI(二)
14. SwiftUI框架詳細(xì)解析 (十四) —— 基于Firebase Cloud Firestore的SwiftUI iOS程序的持久性添加(一)
15. SwiftUI框架詳細(xì)解析 (十五) —— 基于Firebase Cloud Firestore的SwiftUI iOS程序的持久性添加(二)
16. SwiftUI框架詳細(xì)解析 (十六) —— 基于SwiftUI簡單App的Dependency Injection應(yīng)用(一)
17. SwiftUI框架詳細(xì)解析 (十七) —— 基于SwiftUI簡單App的Dependency Injection應(yīng)用(二)
18. SwiftUI框架詳細(xì)解析 (十八) —— Firebase Remote Config教程(一)
19. SwiftUI框架詳細(xì)解析 (十九) —— Firebase Remote Config教程(二)
20. SwiftUI框架詳細(xì)解析 (二十) —— 基于SwiftUI的Document-Based App的創(chuàng)建(一)
21. SwiftUI框架詳細(xì)解析 (二十一) —— 基于SwiftUI的Document-Based App的創(chuàng)建(二)
開始
首先看下主要內(nèi)容:
了解如何使用
AWS AppSync
框架以簡單且類型安全的方式在SwiftUI
iOS應(yīng)用中使用GraphQL API
。內(nèi)容來自翻譯京办。
接著看下寫作環(huán)境:
Swift 5, iOS 14, Xcode 12
最后看正文掀序。
如今,大多數(shù)應(yīng)用程序都需要后端才能工作惭婿。需要用戶帳戶嗎?為此财饥,您需要一個(gè)后端。要跨設(shè)備同步數(shù)據(jù)嗎沾瓦?猜猜是什么贯莺,您需要一個(gè)后端宁改。有針對(duì)性的推送通知?后端……您明白了爹耗。
您可能之前曾聽說過縮寫BaaS (Back end as a service)
豁鲤。BaaS
工具通過使用簡單的API與云存儲(chǔ)服務(wù)集成。配置完成后鲸沮,這些BaaS
服務(wù)將以與其他任何API相同的方式運(yùn)行琳骡,而幾乎不需要或不需要任何前端知識(shí)。
在本教程中讼溺,您將使用Amazon
的名為AppSync
的BaaS
產(chǎn)品以及Amplify
框架向iOS應(yīng)用添加后端組件楣号。您將學(xué)習(xí)如何:
- 安裝
AWS Amplify
及其依賴項(xiàng) - 使用
GraphQL
實(shí)現(xiàn)模型并使用Amplify
生成本地文件 - 對(duì)數(shù)據(jù)執(zhí)行
CRUD
操作 - 將您的應(yīng)用程序數(shù)據(jù)保存到
AWS AppSync
您將通過使用SwiftUI
實(shí)現(xiàn)待辦事項(xiàng)應(yīng)用程序來學(xué)習(xí)所有這些內(nèi)容。該應(yīng)用程序?qū)⒃试S您創(chuàng)建怒坯,刪除和完成待辦事項(xiàng)炫狱,同時(shí)保持應(yīng)用程序的數(shù)據(jù)與AppSync
云服務(wù)同步。該應(yīng)用程序無論有沒有互聯(lián)網(wǎng)連接都可以使用剔猿!
打開啟動(dòng)文件夾中的RazeList.xcodeproj
视译。
RazeList
可以幫助您在所有iOS設(shè)備上保持同步。這是您所有工作的真相之一归敬,更重要的是酷含,您所有的dones
!學(xué)完本教程后汪茧,無論使用哪種設(shè)備椅亚,您都將永遠(yuǎn)知道自己在哪里工作。
在Xcode
中舱污,構(gòu)建并運(yùn)行項(xiàng)目呀舔。
目前,該項(xiàng)目不僅僅是問候惧磺。您將對(duì)此進(jìn)行更改,但是首先需要滿足一些先決條件琳拭。
About GraphQL and AppSync
在編寫任何代碼之前,您首先需要了解GraphQL
是什么以及它如何與AppSync
一起使用絮缅。
1. What is GraphQL?
GraphQL
由Facebook
在2012
年開發(fā)耕魄;它是一種查詢語言和服務(wù)器端運(yùn)行時(shí)允扇,用于執(zhí)行旨在與服務(wù)器端API
配合使用的查詢。
如果您以前使用過服務(wù)器端API糊治,則可能已經(jīng)熟悉REST
井辜。 REST API
通過為應(yīng)用程序公開多個(gè)終結(jié)點(diǎn)來工作抑胎,每個(gè)終結(jié)點(diǎn)均針對(duì)特定的數(shù)據(jù)類型而設(shè)計(jì)赃蛛。如今呕臂,大多數(shù)API都被認(rèn)為是RESTful
的歧蒋。但是,REST
標(biāo)準(zhǔn)的解釋較為寬松阐虚,因此您可能會(huì)在多個(gè)REST API
上有不同的經(jīng)驗(yàn)实束。
與REST
相反构订,GraphQL
僅公開一個(gè)端點(diǎn),您可以通過查詢與之交互分尸。使用這種方法箩绍,客戶端僅訪問他們需要的數(shù)據(jù),并最小化通過網(wǎng)絡(luò)發(fā)送的數(shù)據(jù)量。查看GraphQL
如何運(yùn)行的最佳方法是一個(gè)示例马绝。
type Todo {
id: ID!
name: String!
description: String
completed: Boolean!
}
上面是GraphQL
模式的示例掷邦,描述了Todo
類型,這是構(gòu)建RazeList
時(shí)將使用的基本結(jié)構(gòu)宣蔚。 服務(wù)器定義此類型,以便您可以獲取它篷扩。 假設(shè)您的應(yīng)用程序中有一個(gè)屏幕枢冤,其中列出了所有待辦事項(xiàng),但只需要name
和completed
字段核蘸。 這是使用GraphQL
查詢獲取該屏幕數(shù)據(jù)的方式:
query TodoQuery {
listTodos {
items {
name
completed
}
}
}
該GraphQL
查詢僅通過指定其關(guān)注的字段來訪問所需的數(shù)據(jù)。 您將此查詢發(fā)送到服務(wù)器徙鱼,并且服務(wù)器使用與您的查詢匹配的數(shù)據(jù)結(jié)構(gòu)進(jìn)行響應(yīng)。 以這種方式添加和刪除字段將需要在使用REST
時(shí)對(duì)API進(jìn)行更改绞绒,而在這里蓬衡,您只需在應(yīng)用程序內(nèi)部更改查詢撤蟆,而無需完全修改服務(wù)器盟猖。
2. GraphQL with AWS AppSync
AWS AppSync
可以完成后端Web服務(wù)的所有繁重工作。 它充當(dāng)GraphQL
和其他AWS
服務(wù)(例如數(shù)據(jù)存儲(chǔ)娘汞,緩存和實(shí)時(shí)更新)之間的橋梁惊豺。
AppSync
為您的項(xiàng)目提供了一個(gè)儀表板,您可以在其中查看和查詢數(shù)據(jù)烹俗,以及通過自定義功能添加自定義功能。
您的應(yīng)用將在后臺(tái)通過GraphQL
與AppSync
進(jìn)行通信; 但是置吓,您將使用AppSync iOS
框架來消除很多這種復(fù)雜性。 完成一些配置后戴质,您只會(huì)以一種類型安全的方式談?wù)撃暮蠖恕?/p>
Installing the Amplify Framework
您將從安裝項(xiàng)目依賴項(xiàng)開始。 您可能已經(jīng)安裝了其中的一些(或全部)后专。 在這種情況下,您可以跳到相關(guān)部分型凳。
1. Installing npm
Node Package Manager (npm)
是一個(gè)軟件包管理器和CLI (command line interface)
,用于管理Node.js
軟件包蓄氧。 在此項(xiàng)目中准给,您將使用npm
安裝Amplify CLI
祖灰。
如果不確定是否已安裝npm
叁扫,請打開“終端”并鍵入npm -v
畴蒲,然后按Enter
模燥。 如果已安裝,則應(yīng)該在“終端”窗口中看到打印的版本號(hào)掩宜。
npm
與Node.js
一起安裝蔫骂。 要同時(shí)安裝Node.js
和npm
,請導(dǎo)航到node.js website網(wǎng)站牺汤,然后單擊標(biāo)有LTS
的下載鏈接辽旋。 在撰寫本文時(shí)戴已,當(dāng)前的LTS
版本是14.15.1 LTS
每瞒。
下載完成后挤庇,打開.pkg
文件掷酗,您應(yīng)該看到以下內(nèi)容:
單擊繼續(xù)阿蝶,然后按照步驟進(jìn)行粤蝎。 安裝完成后,重新啟動(dòng)Terminal
并鍵入npm -v
并按Enter。 現(xiàn)在盅粪,您應(yīng)該看到版本號(hào)含鳞。
2. Installing Amplify CLI
通過命令行安裝Amplify
桅狠。 在終端內(nèi)陨仅,鍵入以下內(nèi)容颖侄,然后按Enter。
sudo npm install -g @aws-amplify/cli
根據(jù)需要輸入系統(tǒng)密碼。 npm會(huì)在終端窗口中看到很多活動(dòng)械媒。 安裝Amplify
后,您應(yīng)該會(huì)看到類似以下的內(nèi)容:
----------------------------------------
Successfully installed the Amplify CLI
----------------------------------------
此過程完成后停巷,輸入以下命令始鱼,然后按Enter
:
amplify configure
該命令將在新的瀏覽器窗口中打開AWS
登錄頁面纸厉。 如果您還沒有AWS
帳戶,則需要先注冊一個(gè)帳戶朝抖,然后才能完成此步驟。 注冊非常容易胧卤。 有關(guān)如何執(zhí)行此操作的說明扔水,請參閱 at the AWS knowledge center朝氓。 完成后魔市,請務(wù)必從此開始繼續(xù)本教程主届。
在瀏覽器窗口中登錄到您的AWS
賬戶。 登錄后待德,返回“終端”窗口君丁,然后按Enter
。
接下來将宪,您需要指定您的區(qū)域绘闷。 使用箭頭鍵選擇最能代表您的位置的區(qū)域,然后按Enter较坛。
接下來輸入新用戶的用戶名印蔗,然后按Enter
。 這可以是您想要的任何東西丑勤。
這會(huì)將您定向到AWS
控制臺(tái)以完成設(shè)置华嘹。 使用底部的按鈕單擊整個(gè)設(shè)置過程,并確保在權(quán)限屏幕上選中了AdministratorAccess
法竞。
在用戶設(shè)置成功屏幕上耙厚,將Access key ID
和Secret access key
復(fù)制到安全位置-以后將需要它們。 復(fù)制Secret access key
時(shí)岔霸,請確保單擊Show
薛躬。
返回“終端”窗口,然后按Enter
呆细。
當(dāng)終端提示時(shí)型宝,輸入您的Access Key ID
和Secret Access Key
。
最后侦鹏,在要求輸入Profile Name
時(shí)诡曙,最后一次按Enter
鍵。 這會(huì)將您的配置文件設(shè)置為default
略水。
3. Installing CocoaPods
您將使用CocoaPods
將AppSync
框架添加到您的項(xiàng)目中价卤。 如果您不熟悉CocoaPods
,可以在我們的 CocoaPods Tutorial for Swift教程中了解
CocoaPods
通過Ruby
安裝渊涝,而Ruby
已經(jīng)安裝在Mac
上慎璧。 打開終端,鍵入以下命令跨释,然后按Enter胸私。
sudo gem install cocoapods
短暫的延遲后,您應(yīng)該在終端窗口中看到Successfully installed cocoapods-VERSION
鳖谈。
Adding Amplify to the Project
現(xiàn)在你已經(jīng)設(shè)置好了依賴項(xiàng)岁疼,你可以繼續(xù)在Xcode中設(shè)置項(xiàng)目了。確保你在下一步關(guān)閉Xcode
缆娃,是的捷绒,你沒聽錯(cuò)!
打開一個(gè)終端屏幕瑰排,并使用cd
導(dǎo)航到starter
項(xiàng)目目錄。然后暖侨,在終端窗口中輸入以下內(nèi)容:
pod init
命令執(zhí)行完畢后椭住,您將注意到項(xiàng)目目錄中出現(xiàn)了一個(gè)名為Podfile
的新文件。在一個(gè)文本編輯器中打開Podfile
字逗,添加如下# Pods for RazeList
:
pod 'Amplify'
pod 'Amplify/Tools'
pod 'AmplifyPlugins/AWSAPIPlugin'
pod 'AmplifyPlugins/AWSDataStorePlugin'
回到終端窗口并輸入以下命令:
pod install
幾秒鐘后京郑,您應(yīng)該看到以下消息:
Pod installation complete! There are 4 dependencies from the Podfile and 12 total pods installed.
瞧!就像這樣,您的包已經(jīng)安裝并包含在您的項(xiàng)目中葫掉。
在Finder
中打開項(xiàng)目目錄些举,您將注意到現(xiàn)在有一個(gè)CocoaPods
創(chuàng)建的名為RazeList.xcworkspace
的工作空間文件。雙擊這個(gè)文件俭厚,你的項(xiàng)目就會(huì)在Xcode
中打開金拒。從現(xiàn)在開始使用這個(gè)文件來打開你的項(xiàng)目,而不是RazeList.xcodeproj
套腹,因?yàn)樗行枰囊蕾図?xiàng)。
1. Adding AppSync Script
你快過終點(diǎn)線了资铡。在編寫任何代碼之前电禀,你需要做的最后一件事是在Xcode的Build Phases
選項(xiàng)卡中添加一個(gè)Run Script
。這個(gè)腳本執(zhí)行一些需要在項(xiàng)目中使用AppSync
的任務(wù)笤休。
在Xcode
中選擇RazeList
項(xiàng)目尖飞。在project explorer
中,單擊Build Phases
店雅。單擊+按鈕并選擇New Run Script Phase
政基。
您將注意到列表底部有一個(gè)新的Run Script
條目。單擊箭頭以展開它闹啦。
在頂部的代碼編輯器中沮明,添加以下代碼:
"${PODS_ROOT}/AmplifyTools/amplify-tools.sh"
現(xiàn)在構(gòu)建并運(yùn)行項(xiàng)目。這次的構(gòu)建時(shí)間會(huì)稍長一些窍奋,因?yàn)?code>Xcode將運(yùn)行腳本(Run Script)
作為構(gòu)建過程的一部分執(zhí)行荐健。當(dāng)構(gòu)建完成時(shí),你的項(xiàng)目中會(huì)有更多的文件琳袄;您將在下一節(jié)中使用這些江场。在進(jìn)入下一階段之前等待項(xiàng)目構(gòu)建是很重要的。
2. Initializing Amplify
一旦構(gòu)建過程完成窖逗,您將需要在項(xiàng)目中初始化amplify
址否。當(dāng)您在項(xiàng)目導(dǎo)航器中看到一個(gè)名為AmplifyConfig
的新文件夾時(shí),您就會(huì)知道構(gòu)建已經(jīng)完成了它的工作碎紊。
確保您在終端的項(xiàng)目目錄中佑附,并輸入以下命令:
amplify init
根據(jù)界面提示輸入如下信息:
? Enter a name for the environment
Press Enter
? Choose your default editor
None
? Do you want to use an AWS profile?
Y
? Please choose the profile you want to use
Press Enter for default
在同一個(gè)終端窗口中樊诺,輸入以下命令,然后按Enter
帮匾。
amplify add api
根據(jù)界面提示輸入如下信息啄骇。其他步驟按enter
,使用默認(rèn)設(shè)置瘟斜。
? Please select from one of the below mentioned services:
GraphQL
? Provide API name:
Press Enter to set this to your directory name.
接下來輸入以下命令缸夹。
amplify push
根據(jù)界面提示輸入如下信息。
? Are you sure you want to continue?
Y
? Do you want to generate code for your newly created GraphQL API
N
這可能看起來有很多設(shè)置螺句,但Amplify
已經(jīng)為您做了很多虽惭。您已經(jīng)創(chuàng)建了一個(gè)用戶,設(shè)置了一個(gè)應(yīng)用程序并將其添加到AWS
儀表板蛇尚,創(chuàng)建了一個(gè)GraphQL API
并將其發(fā)布到AWS
芽唇。一切都準(zhǔn)備好了!
Creating Models Using GraphQL
在處理后端服務(wù)時(shí),您可能希望將數(shù)據(jù)類型表示為模型取劫。Amplify
讓你省去了自己打印它們的麻煩匆笤。那不是很好嗎?
但是,您仍然需要告訴Amplify
要生成什么谱邪,這將使用GraphQL
完成!
打開AmplifyConfig
組內(nèi)的schema.graphql
炮捧。
替換該文件的內(nèi)容如下:
type Todo @model {
id: ID!
name: String!
description: String
completed: Boolean!
}
接下來,打開同一個(gè)目錄中的amplifytools.xcconfig
惦银。將push
和modelgen
更改為true
咆课。
構(gòu)建并運(yùn)行項(xiàng)目。構(gòu)建完成后扯俱,項(xiàng)目導(dǎo)航器中會(huì)有一個(gè)名為AmplifyModels
的新目錄书蚪。在配置中更改上面的行告訴Amplify
從GraphQL schema
模式為您生成模型文件,并更新AWS
上的配置迅栅。擴(kuò)大AmplifyModels
殊校,看看周圍系馆。您將看到Todo.swift
包含您的模型和一些幫助文件式矫。
1. Using Amplify in the App
在左側(cè)的項(xiàng)目導(dǎo)航器中孵稽,打開AppMain.swift
并添加以下導(dǎo)入:
import Amplify
import AmplifyPlugins
在AppDelegate
類中诞挨,在application(_:didFinishLaunchingWithOptions:)
函數(shù)返回true
之前添加以下代碼:
let apiPlugin = AWSAPIPlugin(modelRegistration: AmplifyModels())
let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels())
do {
try Amplify.add(plugin: apiPlugin)
try Amplify.add(plugin: dataStorePlugin)
try Amplify.configure()
print("Initialized Amplify")
} catch {
print("Could not initialize Amplify: \(error)")
}
構(gòu)建并運(yùn)行項(xiàng)目镰禾。
沒有任何視覺上的變化州叠,但是您已經(jīng)完全配置了項(xiàng)目以與AppSync
和Amplify
一起使用弊决。
Building the To Do List UI
安裝了庫仅政,設(shè)置了CocoaPods
并生成了模型之后拜英,就該使RazeList
變得栩栩如生了静汤。
本教程的某些SwiftUI
編碼已為您完成,但您仍需要構(gòu)建主要任務(wù)清單。 這就是本節(jié)中要執(zhí)行的操作虫给。
1. Adding Rows to the To Do List
首先定義行藤抡。 右鍵單擊Views
組,然后選擇New File
選項(xiàng)抹估。 選擇SwiftUI View
缠黍,然后單擊Next
。 將文件命名為TodoRowView.swift
并創(chuàng)建它药蜻。
打開該文件瓷式,然后在TodoRowView
聲明下方添加以下內(nèi)容。
// 1
let todoItem: Todo
// 2
let onToggleCompleted: (Todo) -> Void
待辦事項(xiàng)行定義了兩個(gè)要求语泽。
- 1) 用于渲染的
Todo
模型贸典。 - 2) 當(dāng)用戶切換完成狀態(tài)時(shí)調(diào)用的閉包。
這將導(dǎo)致錯(cuò)誤踱卵,因?yàn)轭A(yù)覽沒有傳遞這些依賴項(xiàng)廊驼。 用以下內(nèi)容替換TodoRowView_Previews
的全部內(nèi)容:
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 }
}
}
接下來,您將定義一個(gè)方法惋砂,當(dāng)用戶切換待辦事項(xiàng)時(shí)妒挎。 將以下方法添加到TodoRowView
中:
func toggleCompleted() {
withAnimation {
onToggleCompleted(todoItem)
}
}
此函數(shù)僅將onToggle Completed
封裝在動(dòng)畫塊中,該動(dòng)畫塊將使各節(jié)之間的行移動(dòng)具有動(dòng)畫效果西饵。
接下來饥漫,將整個(gè)body
替換為以下內(nèi)容:
var body: some View {
// 1
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 10) {
// 2
Button(action: { onToggleCompleted(todoItem) }) {
Image(systemName: todoItem.completed ? "checkmark.square" : "square")
.imageScale(.large)
.foregroundColor(todoItem.completed ? .pink : .primary)
}
// 3
Text(todoItem.name)
.font(.system(size: 18, weight: .semibold))
}
// 4
if let description = todoItem.description {
Text(description)
.font(.system(size: 14, weight: .medium))
.padding(.leading, 32)
.padding(.trailing, 10)
.foregroundColor(.gray)
}
}
}
上面的代碼是這樣的:
- 1) 定義一個(gè)
VStack
容器。 - 2) 定義一個(gè)
HStack
罗标,其中包含帶有復(fù)選框圖像的按鈕。 根據(jù)待執(zhí)行模型的completed
屬性的狀態(tài)來選擇是否選中該圖像积蜻。 點(diǎn)擊按鈕將調(diào)用onToggleCompleted(_ :)
闯割。 - 3) 堆棧
stack
中的第二項(xiàng)是包含要執(zhí)行的操作的名稱的Text
視圖。 - 4) 如果待辦事項(xiàng)包含描述竿拆,請?jiān)?code>Text視圖中呈現(xiàn)它宙拉。
2. Setting up Your Data
打開TodoListViewModel.swift
。 在類實(shí)現(xiàn)內(nèi)添加以下代碼:
@Published var todos: [Todo] = []
@Published var completedTodos: [Todo] = []
TodoListViewModel
符合ObservableObject
丙笋。 遵循此協(xié)議谢澈,允許對(duì)象在狀態(tài)更改時(shí)發(fā)布更新。 使用@Published
屬性包裝器告訴對(duì)象通過其發(fā)布者將更改廣播給正在收聽的任何人御板。 當(dāng)對(duì)象更新時(shí)锥忿,SwiftUI
使用它來重繪UI。
如果您想了解有關(guān)ObservableObject
的更多信息怠肋,請查看Combine: Asynchronous Programming with Swift敬鬓。
接下來,打開TodoListView.swift
并在視圖實(shí)現(xiàn)中添加以下代碼:
@ObservedObject var viewModel = TodoListViewModel()
在這里,您將使用@ObservedObject
屬性包裝器創(chuàng)建對(duì)TodoListViewModel
的引用钉答。 以這種方式創(chuàng)建屬性會(huì)告訴SwiftUI
您關(guān)心該對(duì)象的狀態(tài)础芍,并且它應(yīng)該響應(yīng)更改。
3. Adding Sections
接下來数尿,您將定義兩個(gè)部分仑性,一個(gè)用于待辦事項(xiàng),一個(gè)用于完成待辦事項(xiàng)右蹦。 一般來說诊杆,您希望保持body
輕點(diǎn)。 考慮到這一點(diǎn)嫩实,您將把這兩個(gè)部分定義為計(jì)算屬性刽辙。
將第一部分添加到TodoListView
中:
var todoSection: some View {
// 1
Group {
// 2
if viewModel.todos.isEmpty {
Text("Nothing to do!")
} else {
// 3
ForEach(viewModel.todos, id: \.id) { todo in
// 4
TodoRowView(todoItem: todo) { todo in
withAnimation {
// Toggle complete
}
}
.padding(.vertical, 6)
}
.onDelete(perform: viewModel.deleteTodos)
}
}
}
一點(diǎn)一點(diǎn)地:
- 1) 您無法選擇返回
Text
視圖或ForEach
視圖,因此它們被包裝在Group
中甲献。 - 2) 如果列表中沒有待辦事項(xiàng)宰缤,請返回一個(gè)反映此情況的
Text
視圖。 - 3) 如果有待辦事項(xiàng)晃洒,請遍歷每個(gè)步驟以在
ForEach
中執(zhí)行慨灭。 - 4) 對(duì)于列表中的每個(gè)操作,生成一個(gè)
TodoRowView
并傳遞當(dāng)前操作球及。
接下來氧骤,您將完成已完成的任務(wù)。 在todoSection
屬性下方吃引,添加以下內(nèi)容:
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)
}
}
}
唯一的區(qū)別是您已將對(duì)viewModel.todos
的引用替換為viewModel.completedTodos
筹陵。
現(xiàn)在,您已經(jīng)定義了兩個(gè)列表部分镊尺,現(xiàn)在該看看它們的實(shí)際效果了朦佩!
將body
內(nèi)容替換為以下內(nèi)容:
// 1
List {
// 2
Section(header: Text("Todo")) {
todoSection
}
// 3
Section(header: Text("Completed")) {
completedTodoSection
}
}
// 4
.listStyle(GroupedListStyle())
上面的代碼執(zhí)行以下操作:
- 1) 創(chuàng)建一個(gè)列表以包含您先前創(chuàng)建的部分。
- 2) 將“待辦事項(xiàng)”部分嵌入
Section
視圖中庐氮。 - 3) 將完成的待辦事項(xiàng)部分嵌入到
Section
視圖中语稠。 - 4) 為列表提供分組樣式。 這將分隔各節(jié)并應(yīng)用一些默認(rèn)樣式弄砍。
構(gòu)建并運(yùn)行以查看結(jié)果仙畦。
您終于擺脫了hello world
應(yīng)用! 真好
4. Adding a To Do
在本部分的最后部分音婶,您將集成“添加待辦事項(xiàng)”屏幕慨畸。 用戶界面已經(jīng)構(gòu)建,因此這是一個(gè)相當(dāng)簡單的步驟衣式。
轉(zhuǎn)到TodoListView.swift
并在視圖實(shí)現(xiàn)內(nèi)添加一個(gè)新屬性:
@State var addNewTodoPresented: Bool = false
這將負(fù)責(zé)呈現(xiàn)和關(guān)閉添加視圖先口。
在body
的底部型奥,.listStyle(GroupedListStyle())
之后的行上,添加以下視圖修飾符:
// 1
.navigationBarItems(
trailing: Button(action: { addNewTodoPresented.toggle() }) {
Image(systemName: "plus")
.imageScale(.large)
}
)
// 2
.sheet(isPresented: $addNewTodoPresented) {
AddTodoView { name, description in
// add todo
addNewTodoPresented.toggle()
}
}
這看起來有點(diǎn)復(fù)雜碉京,但實(shí)際上相當(dāng)簡單:
- 1)
navigationBarItems(trailing :)
視圖修飾符將導(dǎo)航項(xiàng)添加到封閉的NavigationView
的導(dǎo)航欄中厢汹。 您在此處添加了一個(gè)按鈕,點(diǎn)擊該按鈕即可切換addNewTodoPresented
谐宙。 - 2) 當(dāng)
isPresented
狀態(tài)為true
時(shí)烫葬,sheet(isPresented:content :)
視圖修飾符將顯示一個(gè)模型。 閉包返回要顯示的視圖凡蜻。 在這種情況下搭综,您將返回AddTodoView
。
構(gòu)建并運(yùn)行以查看結(jié)果划栓。
您現(xiàn)在在導(dǎo)航欄中有一個(gè)添加按鈕兑巾,并有一個(gè)屏幕來添加新的待辦事項(xiàng)!
Creating and Editing To Dos
所有人都已設(shè)置完畢忠荞,并具有正常運(yùn)行的用戶界面蒋歌。 您需要做的最后一件事就是將所有東西連接起來!
打開TodoListViewModel.swift
并添加一個(gè)新的導(dǎo)入委煤。
import Amplify
1. Adding To Dos
接下來堂油,添加以下方法:
func createTodo(name: String, description: String?) {
// 1
let item = Todo(name: name, description: description, completed: false)
// 2
todos.append(item)
// 3
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)")
}
}
}
使用前面步驟中的所有配置,這就是將數(shù)據(jù)保存到本地和云數(shù)據(jù)存儲(chǔ)中所需要的全部碧绞。 這是正在發(fā)生的事情:
- 1) 使用傳入的變量創(chuàng)建新的待辦事項(xiàng)府框。
- 2) 將其添加到本地待辦事項(xiàng)
todos
數(shù)組。 - 3) 使用
Amplify
框架讥邻,將to do
添加到您的數(shù)據(jù)存儲(chǔ)中迫靖。
接下來打開TodoListView.swift
,然后向下滾動(dòng)到body
末尾的.sheet
修改器兴使。 在addNewTodoPresented.toggle()
上方一行的閉包中袜香,添加對(duì)createTodo(name:description :)
函數(shù)的調(diào)用。
viewModel.createTodo(name: name, description: description)
您現(xiàn)在可以保存待辦事項(xiàng)鲫惶,但是除非您可以加載它們,否則這樣做是沒有用的实抡!
返回TodoListViewModel.swift
欠母,將loadToDos()
替換為以下內(nèi)容。
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)")
}
}
}
現(xiàn)在吆寨,在TodoListView.swift
中赏淌,在.sheet
下添加一個(gè)新的視圖修改器。
.onAppear {
viewModel.loadToDos()
}
構(gòu)建并運(yùn)行項(xiàng)目以添加您的第一個(gè)待辦事項(xiàng)啄清!
2. Completing To Dos
到目前為止六水,該應(yīng)用程序非常適合向您顯示您需要做的事情-但并不擅長讓您完成這些任務(wù)俺孙。
打開TodoListViewModel
。 滾動(dòng)到底部掷贾,然后在loadTodos()
之后添加以下新方法:
func toggleComplete(_ todo: Todo) {
// 1
var updatedTodo = todo
updatedTodo.completed.toggle()
// 2
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)")
}
}
// 3
if updatedTodo.completed {
if let index = todos.firstIndex(where: { $0.id == todo.id }) {
todos.remove(at: index)
completedTodos.insert(updatedTodo, at: 0)
}
// 4
} else {
if let index = completedTodos.firstIndex(where: { $0.id == todo.id }) {
completedTodos.remove(at: index)
todos.insert(updatedTodo, at: 0)
}
}
}
好的睛榄,這是相當(dāng)一部分代碼。 它的作用是:
- 1) 制作一個(gè)可變的副本即可進(jìn)行修改想帅,然后切換完成的值场靴。
- 2) 使用
Amplify
,將的操作保存回您的數(shù)據(jù)存儲(chǔ)中港准。 - 3) 如果待辦事項(xiàng)已完成旨剥,請將其從待辦事項(xiàng)
todos
中刪除并將其添加到completedTodos
。 - 4) 如果待辦事項(xiàng)尚未完成浅缸,請將其從
completedTodos
中刪除并將其添加到待辦事項(xiàng)中轨帜。
打開TodoListView.swift
并導(dǎo)航到頂部的兩個(gè)屬性。 在todoSection
和completedTodoSection
中衩椒,您會(huì)注意到兩個(gè)占位符注釋// Toggle complete
蚌父。 用以下兩個(gè)地方替換該注釋:
viewModel.toggleComplete(todo)
構(gòu)建并運(yùn)行該應(yīng)用程序。 現(xiàn)在烟具,您可以輕按任一列表中的每個(gè)待辦事項(xiàng)梢什,并以很酷的動(dòng)畫更改完成狀態(tài)!
3. Deleting To Dos
您需要添加的最后一件事是刪除行的方法朝聋。 UI中已經(jīng)存在“滑動(dòng)刪除”功能嗡午,因此您只需將其連接起來即可。
打開TodoListViewModel.swift
冀痕,您會(huì)在頂部注意到三種刪除方法荔睹。 這些將充當(dāng)幫助方法,以從其各自的列表中刪除待辦事項(xiàng)言蛇。
添加以下方法:
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
框架調(diào)用delete(_ :)
從數(shù)據(jù)存儲(chǔ)中刪除模型僻他。
接下來,將以下三種刪除方法替換為:
// 1
func deleteItems(at offsets: IndexSet, from todoList: inout [Todo]) {
for index in offsets {
let todo = todoList[index]
delete(todo: todo)
}
todoList.remove(atOffsets: offsets)
}
// 2
func deleteTodos(at offsets: IndexSet) {
deleteItems(at: offsets, from: &todos)
}
// 3
func deleteCompletedTodos(at offsets: IndexSet) {
deleteItems(at: offsets, from: &completedTodos)
}
這是您所做的:
- 1) 第一個(gè)刪除方法調(diào)用剛添加的
delete(at:from :)
腊尚。 - 2) 此方法使用
todos
數(shù)組路由要?jiǎng)h除的調(diào)用吨拗。 - 3) 此方法使用
completedTodos
數(shù)組路由要?jiǎng)h除的呼叫。
構(gòu)建并運(yùn)行項(xiàng)目婿斥。 您現(xiàn)在可以滑動(dòng)以刪除待辦事項(xiàng)劝篷!
現(xiàn)在,您有一個(gè)待辦事項(xiàng)列表民宿,可用于添加娇妓,編輯和刪除待辦事項(xiàng)。 它可以脫機(jī)工作活鹰,并與AWS
后端保持同步哈恰。
現(xiàn)在只估,您已經(jīng)知道在iOS應(yīng)用中集成和使用AppSync
和Amplify
的基礎(chǔ)知識(shí)-但是還有很多東西要學(xué)習(xí)! GraphQL
可以做的比您在這里介紹的要多得多着绷。
當(dāng)您準(zhǔn)備好使用AWS
和Amplify
進(jìn)行下一步時(shí)蛔钙,請查看 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蓬戚,以查看更多實(shí)際示例夸楣。 您也可以在GraphQL
官方網(wǎng)站official GraphQL website.上了解有關(guān)GraphQL
的更多信息。
您還應(yīng)該查看亞馬遜為進(jìn)一步學(xué)習(xí)而制作的官方AWS AppSync教程official AWS AppSync tutorials子漩。
后記
本篇主要講述了基于基于
SwiftUI
的AWS AppSync
框架的使用豫喧,感興趣的給個(gè)贊或者關(guān)注~~~