第18天 SwiftUI 项目1 第三部分
你刚刚完成了你的第一个 SwiftUI 应用程序开发,一切顺利的话,你可能会惊讶于这个过程竟如此简单。你甚至可能会疑惑,我之前花了那么多时间讲解结构体、闭包、可选类型等等内容,可最终我们写的代码却相当简单。
其实,首先要记住,这只是第一个项目,我特意把它设计得比较简单,这样你就能更快地用自己的代码动手实践。相信我,后续的内容会越来越复杂 —— 事实上,明天你就要独立完成一个属于自己的项目了,所以别太放松!
其次,你其实已经在使用一些高级特性了。实际上,你在不知不觉中已经用到了 Swift 所提供的所有最核心的高级特性。我们一直都在使用闭包,看看下面这样的代码就知道了:
Picker("Tip percentage", selection: $tipPercentage) {
ForEach(tipPercentages, id: \.self) {
Text($0, format: .percent)
}
}你注意到里面的 $0 了吗?这是闭包参数的简写语法,因为我们正处于一个闭包内部。
无论如何,既然这个应用程序已经完成,现在就来快速回顾一下你学到的内容,做一个小测试确保你理解了所教的知识,然后迎接你的第一个挑战 —— 这些练习的目的是让你尽快开始自己编写代码。
我不会提供这些挑战的答案。 这样做是有意为之:我希望你自己去摸索解决,而不是直接看别人的成果。就像马文・菲利普斯(Marvin Phillips)所说:“尝试(try)和成功(triumph)之间,差的只是多一点点的努力(umph)。”
今天,你需要完成项目 1 的总结章节,做完其中的复习内容,然后完成所有三个挑战。
- WeSplit 项目总结
- WeSplit 项目练习题
完成这些之后,去告诉其他人吧:你已经完成了第一个 SwiftUI 项目,通过了测试,甚至还用自己的代码对项目进行了扩展。
你应该为自己取得的成就感到骄傲 —— 干得好!
WeSplit 项目总结
作者:Paul Hudson 2023 年 10 月 8 日
你已经完成了你的第一个 SwiftUI 应用 —— 干得好!我们涵盖了很多内容,但我也尽量放慢节奏,确保你能完全理解 —— 未来的项目中我们还有更多内容要学习,所以现在多花一点时间是值得的。
在这个项目中,你学习了 SwiftUI 应用的基本结构、如何构建表单(forms)和分组(sections)、创建导航栈(navigation stacks)和导航栏标题(navigation bar titles)、如何使用@State和@FocusState属性包装器存储程序状态、如何创建TextField和Picker等用户界面控件,以及如何使用ForEach循环创建视图。更棒的是,通过努力,你现在有了一个可以展示的实际项目。
回顾所学内容
任何人都能看完一个教程,但要记住所学的知识则需要实际付出努力。我的职责是确保你能从这些教程中收获尽可能多的内容,通过完成后面的练习题,帮助你检验自己的学习成果。
挑战任务
学习编程最好的方法之一就是尽可能多地自己编写代码,因此我为你准备了三种扩展这个应用的方式,确保你能完全理解其中的原理:
- 给第三个分组添加一个标题,内容为 “每人应付金额”
- 新增一个分组,显示账单的总金额 —— 即原始金额加上小费金额,不除以人数
- 将小费比例选择器(picker)改为跳转到新屏幕显示,而不是使用分段控制器(segmented control),并提供更广泛的选项范围 —— 从 0% 到 100% 的所有比例。提示:使用
0..<101这个范围,而不是固定的数组。
WeSplit 项目练习题
问题 1/12:以下哪些表述是正确的?
- 选项 1:
VStack可以包含任意数量的子视图。 - 选项 2: 所有 SwiftUI 视图都必须继承自
ContentView协议。
问题 2/12:以下哪些表述是正确的?
- 选项 1: 格式化器(Formatters)可以让我们控制
Text视图中数字的显示方式。 - 选项 2: 我们应该始终强制用户使用特定的货币代码。
问题 3/12:以下哪些表述是正确的?
- 选项 1: SwiftUI 视图不能包含计算属性。
- 选项 2: 在 SwiftUI 中,分段控制器(segmented controls)是通过选择器视图(picker views)创建的。
问题 4/12:以下哪些表述是正确的?
- 选项 1: 表单(Forms)可以滚动。
- 选项 2:
NavigationBar视图可以让我们显示新视图,还能在屏幕顶部放置文本。
问题 5/12:以下哪些表述是正确的?
- 选项 1:
keyboardType()修饰符可以让我们在文本框(text field)处于激活状态时,更改显示的键盘类型。 - 选项 2: 所有表单分组(form sections)都必须有标题。
问题 6/12:以下哪些表述是正确的?
- 选项 1: 创建文本框(text field)时,我们需要提供一些占位文本(placeholder text)。
- 选项 2: 在 iOS 中,选择器(Pickers)始终以滚轮形式显示。
问题 7/12:以下哪些表述是正确的?
- 选项 1: 我们可以使用
@符号声明双向绑定,例如@name。 - 选项 2: 所有 SwiftUI 视图都必须有
body属性。
问题 8/12:以下哪些表述是正确的?
- 选项 1: 我们可以向
navigationTitle()修饰符传递一个字符串,在导航视图顶部显示标题。 - 选项 2: 空合运算符(nil coalescing operator)用于确保使用值之前该值为 nil。
问题 9/12:以下哪些表述是正确的?
- 选项 1: 如果想要修改一个属性,需要使用
@Property这类 SwiftUI 属性包装器。 - 选项 2: 如果想要修改一个属性,需要使用
@State这类 SwiftUI 属性包装器。
问题 10/12:以下哪些表述是正确的?
- 选项 1:
ForEach视图可以让我们遍历范围(ranges)和数组(arrays)。 - 选项 2:
ForEach视图最多只能遍历 10 个项目,因为 SwiftUI 不允许遍历更多项目。
问题 11/12:以下哪些表述是正确的?
- 选项 1: 每当
@State属性发生变化时,Swift 都会重新调用我们的body属性。 - 选项 2: Apple 建议
@State属性应使用公开访问控制(public access control)。
问题 12/12:以下哪些表述是正确的?
- 选项 1: 我们总是需要将文本框(text fields)与字符串(strings)进行绑定。
- 选项 2: 如果我们将应用提交到 App Store,SwiftUI 的预览(previews)不会包含在应用中。