到目前为止,你应该已经开始对 SwiftUI 的工作方式感到熟悉了。我知道,对于某些人来说,这可能是一个巨大的心理障碍,因为我们无法像以前那样控制程序的精确流程,而是需要构建整个状态,然后放手让它运行。然而,现在你已经完成了四个完整的项目,并深入研究了两个技术项目,希望你已经开始掌握 SwiftUI 的工作模式。
处理数字输入
Stepper
从用户那里读取数字,包括其简化形式,当标签是简单的 Text
视图时。日期处理
DatePicker
输入日期,包括使用 displayedComponents
参数控制显示日期或时间。Date
、DateComponents
和 DateFormatter
在 Swift 中处理日期。机器学习
创建数据表
List
构建滚动表格,特别是直接从数组创建行的方式。视图生命周期
onAppear()
在视图显示时运行代码。文件读取
Bundle
类查找文件路径,从应用包中读取文件,包括加载字符串内容。处理崩溃
fatalError()
让代码崩溃,并理解为何这可能是一个好方法。字符串校对
UITextChecker
检查字符串拼写是否正确。动画基础
animation()
修饰符创建隐式动画。动画绑定
animation()
修饰符附加到绑定上,从而直接通过 UI 控件为状态变化添加动画。显式动画
withAnimation()
创建显式动画。动画堆栈
animation()
修饰符,以控制动画堆栈。拖动手势
DragGesture()
允许用户移动视图,并将其快速恢复到原始位置。转场
是的,在短短三个项目中,这涉及到大量的新信息。但由于每个主题都先被独立讲解(例如“列表是如何工作的?”),然后在实际项目中使用(“现在我们在这里使用列表”),希望你已经将这些知识融会贯通。如果没有,请不要害怕回头复习之前的章节——它们随时可以参考,并且对你掌握 SwiftUI 大有帮助。
即使你开始理解 SwiftUI 的工作原理,你可能仍然会发现很难准确表达你的需求。
动画 就是一个典型的例子:我们想要对某个按钮说“让它——就是这个——立刻旋转”。但 SwiftUI 并不是为这种命令式思维设计的。我们无法直接对按钮说“旋转”。
在 SwiftUI 中,所有的视图和动画都必须是状态的函数。这意味着我们不直接告诉按钮旋转,而是将按钮的旋转角度绑定到某个状态上,并在需要时修改该状态。这种思维方式的转变,特别是对有编程经验的人来说,可能会感到格外困难,因为他们已经习惯了命令式思维——在这种思维下,他们能轻松地控制一切。
如果你在学习过程中感到卡住了,请放轻松——这是正常的,你并不孤单。如果你尝试了一个小时甚至两小时,还是无法解决问题,建议先放下它,转而尝试下一个项目。一周后再回头看,你会发现自己知道得更多,实践得更熟练,并且拥有全新的视角。
让我们继续保持专注和耐心,SwiftUI 的旅程仍在继续!
到目前为止,你已经完成了两个 SwiftUI 项目,并完成了一个技术项目。我们将继续遵循“两项目 + 一个技术项目”的节奏,这种安排既能快速提升你的知识,又能通过复习巩固所学。
尽管我们只完成了三个项目,但你已经掌握了 SwiftUI 中的一些核心概念:**视图(Views)、修饰符(Modifiers)、状态(State)、堆叠布局(Stack Layouts)**等等——这些都是 SwiftUI 中的基础技能,你会在未来的项目中反复运用。因此,我们在初期就重点讲解这些概念,以确保你扎实掌握。
当然,在这过程中,你还完成了一些真实的项目和代码挑战,希望你已经对自己的学习成果有了更多的信心。
Picker
),SwiftUI 会自动将其转换为美观的基于表格的布局,并支持新界面滑入显示。NavigationStack
创建导航,并设置标题。它不仅支持向屏幕推送新视图,还避免了内容被状态栏遮挡的问题。@State
存储可变数据,以及为什么需要它。SwiftUI 的视图是结构体,无法直接更改,因此需要 @State
来管理状态。TextField
和 Picker
等 UI 控件创建双向绑定,通过 $variable
同时读取和写入值。ForEach
循环创建视图,可以一次性生成大量视图。VStack
、HStack
和 ZStack
构建复杂布局,并结合使用它们创建网格。some View
),以及这如何与修饰符的顺序相关。你可能开始对 SwiftUI 中的“视图”有了新的理解。在开始课程之前,你可能会认为像 Color.red
不可能是视图,但事实是,它就是视图。同样,LinearGradient
也是视图,因此可以轻松用在布局中。
那么 VStack
、Group
和 ForEach
呢?
是的,这些也都是 SwiftUI 中的视图。这种灵活的组合性使得我们可以将一个 ForEach
嵌套在另一个 ForEach
中,再嵌套在一个 Group
和 VStack
中——它都能正常运行。
为什么这如此重要?
在 SwiftUI 中,只要一个类型符合 View
协议,并拥有一个返回 some View
的 body
属性,它就可以作为视图参与布局。这种协议的力量让 SwiftUI 的设计变得简洁而强大。
在其他界面框架(包括 Apple 的 UIKit)中,通常使用类来实现这种功能。这要求你从 UIView
继承,而 UIView
会带来许多你可能用不到的属性和方法,增加了不必要的复杂性。而 SwiftUI 中,你只需要让类型符合 View
协议即可。这正是协议和协议扩展的力量所在,也是协议导向编程的重要性。
你可能注意到一个有趣的现象:我们创建的 SwiftUI 视图会返回其他视图,而那些视图也会返回更多的视图……似乎是一个无限循环。
实际上,这个循环最终会结束,而答案就在于 SwiftUI 的“原始视图(Primitive Views)”。这些是 SwiftUI 的最基本构建块,它们符合 View
协议,但返回固定内容,而不是进一步嵌套其他视图。
常见的原始视图:
Text
Image
Color
Spacer
我们构建的所有 UI 最终都是基于这些基础构建块,这也打破了看似无限的循环。
通过这些学习,你已经掌握了 SwiftUI 的核心思想和技术基础。继续努力,SwiftUI 的旅程才刚刚开始!