Skip to content

第18天 SwiftUI 项目1 第三部分

你刚刚完成了你的第一个 SwiftUI 应用程序开发,一切顺利的话,你可能会惊讶于这个过程竟如此简单。你甚至可能会疑惑,我之前花了那么多时间讲解结构体、闭包、可选类型等等内容,可最终我们写的代码却相当简单。

其实,首先要记住,这只是第一个项目,我特意把它设计得比较简单,这样你就能更快地用自己的代码动手实践。相信我,后续的内容会越来越复杂 —— 事实上,明天你就要独立完成一个属于自己的项目了,所以别太放松!

其次,你其实已经在使用一些高级特性了。实际上,你在不知不觉中已经用到了 Swift 所提供的所有最核心的高级特性。我们一直都在使用闭包,看看下面这样的代码就知道了:

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属性包装器存储程序状态、如何创建TextFieldPicker等用户界面控件,以及如何使用ForEach循环创建视图。更棒的是,通过努力,你现在有了一个可以展示的实际项目。

回顾所学内容

任何人都能看完一个教程,但要记住所学的知识则需要实际付出努力。我的职责是确保你能从这些教程中收获尽可能多的内容,通过完成后面的练习题,帮助你检验自己的学习成果。

挑战任务

学习编程最好的方法之一就是尽可能多地自己编写代码,因此我为你准备了三种扩展这个应用的方式,确保你能完全理解其中的原理:

  1. 给第三个分组添加一个标题,内容为 “每人应付金额”
  2. 新增一个分组,显示账单的总金额 —— 即原始金额加上小费金额,不除以人数
  3. 将小费比例选择器(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)不会包含在应用中。

本站使用 VitePress 制作