本课目标:装好 Xcode,创建第一个 SwiftUI 项目,理解 Text、Image、Button、VStack、@State、#Preview,并完成一个能点击交互的小计数器。
一、准备与新建项目
- 在 Mac App Store 安装 Xcode。
- 打开 Xcode,选择 File → New → Project → iOS → App。
- Product Name 填 HelloSwiftUI。
- Interface 选 SwiftUI,Language 选 Swift。
- 打开 ContentView.swift,开始写代码。
二、第一个 SwiftUI 程序:详细注释版
swift
import SwiftUI // 导入 SwiftUI 框架,才能使用 View、Text、VStack 等类型
struct ContentView: View { // 定义一个视图结构体,并遵循 View 协议
var body: some View { // body 是视图必须实现的属性,用来描述界面内容
VStack { // VStack:垂直堆叠容器,子视图从上到下排列
Image(systemName: "globe") // 使用 SF Symbols 显示一个地球图标
Text("Hello, world!") // 显示一段文本
}
.padding() // 给 VStack 四周增加默认内边距,让内容不贴边
}
}
#Preview { // Xcode 预览宏,用于实时查看界面效果
ContentView() // 预览 ContentView
}
三、动手改:计数器:详细注释版
swift
import SwiftUI // 导入 SwiftUI
struct ContentView: View {
// @State:声明视图内部状态,值变化后会自动刷新界面
// private:表示这个状态只在本视图内部使用,外部不能直接修改
@State private var count = 0 // 计数器,初始值为 0
var body: some View {
VStack(spacing: 16) { // 垂直排列子视图,间距为 16
Image(systemName: "swift") // 显示 Swift 系统图标
.font(.system(size: 50)) // 设置图标大小为 50
.foregroundStyle(.orange) // 设置图标前景色为橙色
Text("你好,SwiftUI!")
.font(.largeTitle) // 使用大标题字体
.foregroundStyle(.blue) // 设置文字颜色为蓝色
Text("计数:\(count)") // 字符串插值:把 count 的值嵌入文本中
HStack { // HStack:水平堆叠容器,子视图从左到右排列
Button("加一") { // 创建标题为"加一"的按钮
count += 1 // 点击后 count 加 1,@State 触发界面刷新
}
Button("减一") {
count -= 1 // 点击后 count 减 1
}
Button("重置") {
count = 0 // 点击后 count 恢复为 0
}
}
.buttonStyle(.borderedProminent) // 给这一组按钮应用突出边框样式
}
.padding() // 给整个 VStack 四周增加内边距
}
}
#Preview { // 实时预览
ContentView()
}
四、习题、答案与解读
选择题
题1
题目:SwiftUI 中,一个视图类型通常用哪个关键字声明?
A. class B. struct C. enum D. protocol
要求:选出正确选项。
答案:B
解读:SwiftUI 视图通常是 struct,轻量且值语义,适合描述 UI。
题2
题目:让 Text 随数据变化自动更新,通常用哪个属性包装器?
A. @State B. @Binding C. @ObservedObject D. @Environment
要求:选出正确选项。
答案:A
解读:@State 用于视图内部简单状态,变化后会触发 body 重新计算。
题3
题目:设置文字颜色,较新的写法是?
A. .color B. .foregroundStyle C. .tint D. .background
要求:选出正确选项。
答案:B
解读:.foregroundStyle(.blue) 是较新的前景色设置方式,适用于文字和图标。
题4
题目:新建 SwiftUI 项目时,Interface 应选?
A. Storyboard B. SwiftUI C. UIKit D. Objective-C
要求:选出正确选项。
答案:B
解读:新建 iOS App 时,Interface 选 SwiftUI,Xcode 会生成 ContentView.swift。
题5
题目:下列哪个是垂直布局容器?
A. HStack B. ZStack C. VStack D. List
要求:选出正确选项。
答案:C
解读:VStack 垂直排列子视图;HStack 水平排列,ZStack 层叠排列。
判断题
题1
题目:SwiftUI 是声明式 UI。
要求:判断对错。
答案:对
解读:你描述"界面应该是什么样",SwiftUI 负责根据状态更新界面。
题2
题目:@State private var count = 0 中 private 不是必须,但推荐。
要求:判断对错。
答案:对
解读:private 防止外部误改状态,状态通常由当前视图自己管理。
题3
题目:修改静态文字必须用 @State。
要求:判断对错。
答案:错
解读:静态文字直接写 Text("你好") 即可,只有会变化并驱动 UI 更新的数据才需要状态。
题4
题目:Image(systemName: "swift") 可以显示系统图标。
要求:判断对错。
答案:对
解读:systemName 使用 SF Symbols 图标库,swift 是其中一种图标。
题5
题目:body 中通常返回一个视图,多条内容可用 VStack 包裹。
要求:判断对错。
答案:对
解读:body 需要返回单个视图,多个子视图可用 VStack、HStack 等容器组合。
填空题
题1
题目:视图必须实现 var ______: some View。
要求:填入空白处。
答案:body
解读:遵循 View 协议后,必须实现 body 属性来描述界面。
题2
题目:按钮点击事件写在 Button("标题") { ______ } 中。
要求:填入空白处。
答案:点击后要执行的代码
解读:Button 的尾随闭包就是点击动作,例如 count += 1。
题3
题目:让视图四周留白用 .______()。
要求:填入空白处。
答案:padding
解读:.padding() 给视图增加内边距,让内容不贴边。
题4
题目:显示变量 count 用字符串插值:Text("计数:______")。
要求:填入空白处。
答案:(count)
解读:Swift 字符串插值使用 (变量),可把数值嵌入文本。
题5
题目:实时预览常用宏:______ { ContentView() }。
要求:填入空白处。
答案:#Preview
解读:#Preview 是 Xcode 预览宏,能实时查看界面效果。
改错题
题1
题目:
swift
struct ContentView {
var body: some View {
Text("你好")
}
}
要求:找出错误并改正。
答案:
swift
struct ContentView: View {
var body: some View {
Text("你好")
}
}
解读:视图必须遵循 View 协议,否则 body 和修饰符无法正常工作。
题2
题目:
swift
struct ContentView: View {
var body: some View {
VStack {
Text("计数:\(count)")
Button("加一") {
count += 1
}
}
.padding()
}
}
要求:找出错误并改正。
答案:在 body 前添加:
swift
@State private var count = 0
解读:count 未定义;而且它需要驱动界面更新,所以要用 @State。
题3
题目:
swift
struct ContentView: View {
var body: some View {
VStack {
Text("你好")
}
padding()
}
}
要求:找出错误并改正。
答案:
swift
struct ContentView: View {
var body: some View {
VStack {
Text("你好")
}
.padding()
}
}
解读:SwiftUI 修饰符要用点语法 .padding(),不能直接写 padding()。
代码预测题
题目:
swift
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack {
Text("计数:\(count)")
Button("加一") {
count += 1
}
}
}
}
要求:写出点击"加一"3 次后界面显示什么。
答案:计数:3
解读:每次点击执行 count += 1,@State 触发 body 重新计算,界面刷新。
编程题
题1
题目:制作个人名片,包含图标、名字和一句自我介绍。
要求:使用 VStack、Image(systemName:)、Text 和修饰符。
参考代码:
swift
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
Image(systemName: "person.circle")
.font(.system(size: 60))
Text("小明")
.font(.title)
Text("正在学习 SwiftUI")
.foregroundStyle(.blue)
}
.padding()
}
}
解读:VStack 垂直排列内容,Image(systemName:) 显示系统图标,.font 和 .foregroundStyle 控制样式。
题2
题目:制作计数器,支持加一、减一、重置。
要求:使用 @State 保存计数,用按钮修改状态。
参考代码:
swift
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack(spacing: 16) {
Text("计数:\(count)")
HStack {
Button("加一") { count += 1 }
Button("减一") { count -= 1 }
Button("重置") { count = 0 }
}
}
.padding()
}
}
解读:@State 保存计数,按钮闭包修改状态,HStack 水平排列按钮。
题3
题目:加一个按钮,点击后切换文字颜色。
要求:使用布尔状态控制颜色。
参考代码:
swift
struct ContentView: View {
@State private var isBlue = true
var body: some View {
VStack(spacing: 16) {
Text("我会变色")
.foregroundStyle(isBlue ? Color.blue : Color.orange)
Button("切换颜色") {
isBlue.toggle()
}
.buttonStyle(.borderedProminent)
}
.padding()
}
}
解读:用布尔状态 isBlue 控制颜色;toggle() 在 true 和 false 之间切换,界面随之更新。
开放思考题
题1
题目:为什么 SwiftUI 常用 struct 描述视图?
要求:简要回答。
参考:struct 值语义轻量,适合描述 UI;状态驱动,减少手动同步。
解读:SwiftUI 通过比较视图值来决定更新,struct 更符合这种声明式模型。
题2
题目:@State 为什么常写成 private?
要求:简要回答。
参考:private 防止外部误改,状态应由视图自己管理。
解读:状态是视图内部实现细节,外部不应直接依赖或修改。
题3
题目:Xcode 预览对开发效率有什么帮助?
要求:简要回答。
参考:预览能实时查看效果,减少反复编译运行。
解读:改代码后预览快速刷新,适合边练边学,及时验证理解。
五、全课知识点总结
· 项目:新建 iOS App,Interface 选 SwiftUI。示例:HelloSwiftUI。
· 视图:遵循 View,实现 body。示例:struct ContentView: View。
· 文本:使用 Text 显示文字。示例:Text("你好")。
· 图标:使用 Image(systemName:) 显示系统图标。示例:Image(systemName: "swift")。
· 按钮:使用 Button 加闭包响应点击。示例:Button("点我") { ... }。
· 布局:使用 VStack 垂直排列,HStack 水平排列。示例:VStack { ... }。
· 修饰符:字体、颜色、留白等。示例:.font(.largeTitle)、.foregroundStyle(.blue)、.padding()。
· 状态:使用 @State 驱动更新。示例:@State private var count = 0。
· 预览:使用 #Preview 实时查看界面。示例:#Preview { ContentView() }。
· 插值:使用 (变量) 把变量嵌入文本。示例:Text("计数:(count)")。
本课达标标准:能独立创建 SwiftUI 项目,修改文字和图标,添加按钮,用 @State 做计数器,并能通过预览实时查看效果。