Skip to content
JLU iOS CLUB / FIELD NOTES

SwiftUI 入门,搭建游戏界面

第一讲讲义:SwiftUI 结构、布局、修饰符、ForEach 与 enum 状态建模。

FIELD NOTES01

从一个 CodeBreaker 界面开始,认识 SwiftUI 的声明式结构、布局和状态表达。跟随讲义在 Xcode 中逐段修改与预览,理解代码如何变成屏幕上的画面。

阅读目录 · 14 节
  1. 1) Swift 与 SwiftUI 的一句话理解
  2. 2) Xcode 三大区域:左中右怎么用
  3. 3) SwiftUI 核心结构:App / Scene / View / struct / protocol
  4. 4) 布局容器:VStack / HStack / ZStack
  5. 5) modifier 修饰符:顺序为何会改变结果
  6. 6) CodeBreaker 页面拆解
  7. 7) 数据与珠子视图:let/var 与可扩展 Pegs
  8. 8) ForEach:循环与 id 的坑
  9. 9) MatchPegs:黑钉/白钉/空 + 深色模式
  10. 10) enum:让状态表达更清楚
  11. 11) 常见错误清单
  12. 12) 任务与挑战
  13. 13) 实现约束
  14. 这节课真正要带走的能力

学习目标。 理解 SwiftUI 的声明式与状态驱动模型

核心能力。 布局容器、修饰符顺序、组件封装、枚举建模

实践方式。 以 CodeBreaker UI 为主线,边讲边改边预览

适配要求。 iPhone 运行正常,Light / Dark Mode 都可读

阅读建议: 按章节顺序走一遍,并在 Xcode 同步跟敲。每一节里都给了最小可运行写法。
项目 GitHub:https://github.com/Hean-Yi/CodeBreaker.git

1) Swift 与 SwiftUI 的一句话理解 ​

Swift 是现代多范式语言,支持面向对象、面向协议和函数式特性。

SwiftUI 是声明式、状态驱动的 UI 框架。你描述“当前状态下界面应该是什么样”,状态变了,界面自动同步刷新。

直观对比:UIKit 更像手工搬砖,SwiftUI 更像配置目标效果。

2) Xcode 三大区域:左中右怎么用 ​

  • 左侧 Project Navigator: 文件与资源管理,如 Assets.xcassets 与 Swift 文件。
  • 中间 Editor: 代码编辑与报错定位。
  • 右侧 Canvas Preview: 实时预览 UI,学习阶段建议常开。

3) SwiftUI 核心结构:App / Scene / View / struct / protocol ​

1. 从入口到视图:先理解“层级关系” ​

@main 声明应用入口,App 提供 Scene,Scene 承载页面,页面由 View 组成,通常以 struct 实现。

App Scene View Struct 层级关系
图 1:App / Scene / View / Struct 的层级和职责。

关键理解:some View / some Scene 是不透明返回类型。你返回的是具体类型,但对外隐藏类型细节。

4) 布局容器:VStack / HStack / ZStack ​

2. 容器决定方向,修饰符决定观感 ​

  • VStack:从上到下排。
  • HStack:从左到右排。
  • ZStack:前后叠放,后写的盖在前面。
VStack HStack ZStack 三种容器
图 2:容器三兄弟对应三种排布模型。

5) modifier 修饰符:顺序为何会改变结果 ​

3. 修饰符是“逐层包裹”,不是独立开关 ​

同一组修饰符,顺序不同,最终渲染不同。最常见是 padding 与 background。

修饰符顺序影响显示范围
图 3:`padding` 与 `background` 顺序变化会改变背景覆盖范围。

进阶组合也一样:clipShape、shadow、frame、onTapGesture 的先后会影响视觉与交互命中范围。

修饰符组合常见陷阱
图 4:修饰器链路会影响阴影是否可见、点击区域是否正确。

6) CodeBreaker 页面拆解 ​

本次课堂先实现基础版 UI,可拆成两块:

  • 一排猜测珠子(Pegs Row)。
  • 一组反馈钉子(MatchPegs,2x2 布局)。

7) 数据与珠子视图:let/var 与可扩展 Pegs ​

4. 变量语义:优先 let,必要时再 var ​

不变数据优先 let,变化数据再用 var。这会直接减少状态错误和误改。

let 与 var 区别
图 5:常量与变量职责分离,有助于代码稳定性。

珠子行建议写成可扩展函数或组件,支持 3~6 个甚至更多:

swift
func pegsView(colors: [Color]) -> some View {
    HStack {
        ForEach(colors.indices, id: \.self) { index in
            RoundedRectangle(cornerRadius: 10)
                .foregroundStyle(colors[index])
                .aspectRatio(1, contentMode: .fit)
        }
    }
}

8) ForEach:循环与 id 的坑 ​

5. 重复元素不要直接用 id: \.self ​

当数组内元素可能重复(例如两个相同颜色),id: \.self 可能导致身份冲突。更稳妥的是用下标或 Identifiable。

ForEach 与 id 的坑
图 6:ForEach 的核心不是“循环”,而是“稳定身份识别”。

9) MatchPegs:黑钉/白钉/空 + 深色模式 ​

  • exact:黑钉(颜色对、位置对)。
  • inexact:白钉(颜色对、位置错)。
  • noMatch:空钉(透明占位,保留布局)。

配色建议使用语义色(如 .primary),让 Light / Dark 自动适配,避免手写颜色在深色模式失真。

10) enum:让状态表达更清楚 ​

6. 不要用魔法数字表达状态 ​

用 enum 明确状态语义,switch 分发行为,可读性和可维护性都更高。

Enum 管理状态
图 7:枚举能把“看不懂的数字状态”升级为“可读的业务状态”。
swift
enum Match {
    case exact
    case inexact
    case noMatch
}

11) 常见错误清单 ​

  1. 返回视图的函数请写 -> some View,不要写 -> View。
  2. 统计计数通常用 filter { ... }.count。
  3. ForEach 的 id 要稳定,不要盲目 \.self。
  4. 深色模式尽量使用语义色(.primary、.secondary)。

12) 任务与挑战 ​

任务 1-3(基础必做)。

  • 完成 CodeBreaker UI 原型:Pegs + MatchMarkers。
  • 做原生场景 Preview:dummy pegs + MatchMarkers 组合预览。
  • 让 MatchMarkers 支持 3~6 个结果,不写死 4 个。

任务 4-6(验证完整性)。

  • Preview 覆盖 3/4/5/6 以及混合状态组合。
  • dummy pegs 数量需与 matches 数量一致。
  • Light / Dark 都要验证可读性与边界表现。

挑战 1-2(组件化)。

  • PegsRow 与 MatchMarkers 组件化,外部只传数据。
  • peg 数量参数化(3~6),Preview 里做参数扫描。

挑战 3-4(工程化 + 视觉)。

  • 做异常输入保护(截断/断言/可读 debug 信息)。
  • 尝试 Material 拟态玻璃效果并保持深浅色可读。

13) 实现约束 ​

  • 状态表达:enum Match { case exact, inexact, noMatch }。
  • ForEach:提供稳定 id(下标或 Identifiable)。
  • 允许在 View 里用 if 分支处理显示逻辑(@ViewBuilder 语义下)。
  • 项目里至少体现一次“修饰符顺序影响结果”的正确实践。

这节课真正要带走的能力 ​

把讲义中的概念用到自己的项目里,在修改、运行与解释代码的过程中巩固理解。