Skip to content

SwiftUI 入门讲义 · CodeBreaker UI 从 0 到 1

这份讲义对应本次冬季 SwiftUI 课程,重点建立「结构化思维 + 可扩展实现」:先搭框架,再写细节。

🧭

学习目标

理解 SwiftUI 的声明式与状态驱动模型

🧱

核心能力

布局容器、修饰符顺序、组件封装、枚举建模

🧪

实践方式

以 CodeBreaker UI 为主线,边讲边改边预览

📱

适配要求

iPhone 运行正常,Light / Dark Mode 都可读

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

目录

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

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` 语义下)。
  • 项目里至少体现一次“修饰符顺序影响结果”的正确实践。

这节课真正要带走的能力

把界面拆成可复用小组件,用数据驱动状态,再用稳定 id 和清晰枚举保证可扩展。学会这套方法,后续任何 SwiftUI 页面都能独立搭起来。

本站点基于 MIT License 发布