WWDC Quick Look 💓 By SwiftGGTeam
Build a SwiftUI view in Swift Playgrounds

Build a SwiftUI view in Swift Playgrounds

观看原视频

Highlight

Apple 演示了在 Xcode-compatible Swift Playground 中用 PlaygroundSupport 显示 SwiftUI live view,并用多文件、环境修饰符、@State 和 Button 做可交互预览,让开发者能在 iPad 或 Mac 上验证 SwiftUI 原型。

核心内容

很多人把 Swift Playgrounds 当成学习 Swift 的入口。这个 session 的开场提醒开发者,它也可以承担更实际的原型工作:在 iPad 或 Mac 上创建 Xcode Playground,写 SwiftUI view,运行 live view,再把结果带回 Xcode。

演讲者用一个任务追踪 app 的进度视图做例子。目标很小:画一个圆形进度摘要,中心显示百分比。放在完整工程里调试会打断思路;放在 Playground 里,可以先用 CircleZStackText 拼出形状,再用运行按钮或 Command-R 看结果。

Swift Playgrounds 的价值不止是跑一段 SwiftUI。它提供代码补全、颜色 literal、拖动大括号包住已有代码、键盘快捷键等编辑能力。视图变复杂后,还可以把 ProgressView 移到单独文件,把主页面留给预览代码。

最后一段把 Playground 变成了自定义 preview canvas。主页面创建 Preview view,一次显示两个 ProgressView,其中一个切到 dark mode。再加上 @StatewithAnimationButton,live view 就能测试不同进度值和动画手感。

详细内容

建立 SwiftUI live view

02:23)演讲者先创建一个 blank Xcode Playground,因为后续工作会带回 Xcode。写 SwiftUI view 时,主页面需要导入 SwiftUI,也需要导入 PlaygroundSupport 来控制 live view。

import SwiftUI
import PlaygroundSupport

关键点:

  • SwiftUI 提供 ViewTextCircleZStackVStack 等界面类型。
  • PlaygroundSupport 提供自定义 Playground 行为的入口。
  • transcript 明确说明它用于 showing live views。
  • 这个选择让 Playground 页面可以承载 SwiftUI 预览,而不是只输出控制台结果。

03:05)有了 ProgressView 后,主页面用当前 Playground page 设置 live view。运行代码后,SwiftUI view 会显示在 Playground 的 live view 区域。

PlaygroundPage.current.setLiveView(ProgressView())

关键点:

  • PlaygroundPage.current 访问当前页面。
  • setLiveView 把一个 SwiftUI view 交给 Playground 显示。
  • ProgressView() 是演示中的原型视图。
  • 这一步把 SwiftUI 编写和可视结果连在一起。

从简单形状搭出进度视图

03:59)进度视图先从一个圆开始。演讲者使用 Circle,加上 stroke 和前景色,再通过 Command-R 运行查看结果。

Circle()
	.stroke(lineWidth: 25)
	.foregroundColor(.blue)

关键点:

  • Circle() 是 SwiftUI 的基础形状。
  • .stroke(lineWidth: 25) 让圆显示成描边。
  • .foregroundColor(.blue) 给描边设置颜色。
  • 运行后发现尺寸和线宽不合适,演讲者继续直接调整数值。

05:03)圆太大时,示例给整个视图加 padding。这个片段也展示了 Playground 适合做视觉参数试验:修改一个数字,马上重新运行比较结果。

ProgressView().padding(150)

关键点:

  • ProgressView() 是要显示的 SwiftUI 视图。
  • .padding(150) 给外层增加固定留白。
  • 这个修改发生在 live view 初始化处,不需要先改完整 app 布局。
  • transcript 中演讲者用 Command-R 反复运行,直到效果接近预期。

05:17)中心百分比通过 ZStack 叠在圆上。演讲者还演示了 Swift Playgrounds 的大括号拖动:把 closing brace 向下拖,就能把已有 circle 代码包进新的 stack。

ZStack { }

关键点:

  • ZStack 用于把子视图叠放在同一平面。
  • 空的 { } 是官方片段,后续操作把已有 circle 代码放进它。
  • 这一步解决的是布局结构,不是视觉参数。
  • Playground 的 brace dragging 减少了手动剪切缩进的操作。

05:50)圆心的百分比先硬编码成文本。对原型来说,这一步足够验证视觉位置。

Text("25%")

关键点:

  • Text("25%") 是 SwiftUI 文本视图。
  • 它放进 ZStack 后会和圆形进度叠在一起。
  • transcript 里先写死 25 percent,后面才把进度变成状态。
  • 这种顺序适合原型:先验证形状,再接入数据。

把视图拆到单独文件

08:07)视图变复杂后,演讲者新建 ProgressView 文件,把 ProgressView struct 从主页面剪切过去。因为它进入了单独模块,类型、body 和 initializer 都需要公开。

public struct ProgressView: View {

关键点:

  • public 让主页面能访问单独文件中的 ProgressView
  • View 协议仍来自 SwiftUI,所以新文件也需要 import SwiftUI
  • transcript 明确说这是因为代码现在在 separate module。
  • 主页面因此可以专注写预览,而不是混放实现代码。

09:35)Swift Playgrounds 会在问题点提示修复。演讲者点击 issue dot,接受 fix-it,把 body 也改成 public。

public var body: some View {

关键点:

  • SwiftUI view 的 body 是外部使用该 view 时需要访问的属性。
  • some View 保持返回类型不暴露具体组合视图。
  • 这个片段来自官方代码 snippet,不是手写补全。
  • Playgrounds 的 issue dot 和 fix-it 帮助快速修正访问控制。

09:43)演讲者还把 initializer 标记为 public,因为主页面接下来要创建不同进度值的 ProgressView

public init(_ progress: Double = 0.3) {

关键点:

  • initializer 接收 Double 类型进度值。
  • 默认值是 0.3,不传参数时也能创建视图。
  • 它必须 public,主页面才能调用。
  • 这为后面的自定义 preview 输入做准备。

创建 light mode 和 dark mode 预览

10:06)主页面新建 Preview view,把多个 ProgressView 放进 VStack。这利用了 transcript 中的关键事实:整个 live view 区域都是 canvas,可以显示多份视图。

VStack(spacing: 30) {
  ProgressView()
  ProgressView()
}

关键点:

  • VStack(spacing: 30) 垂直排列两个进度视图。
  • 两个 ProgressView() 可以用于比较不同环境。
  • 这个结构让 Playground live view 成为自定义 preview。
  • 它对应 transcript 中“show my view more than once”的目标。

10:49)为了看清浅色和深色模式差异,预览外层加了系统背景色。演讲者让代码补全填入 UIKit 的 secondarySystemBackground

.background(Color(UIColor.secondarySystemBackground))

关键点:

  • Color(UIColor.secondarySystemBackground) 把 UIKit 系统颜色桥接到 SwiftUI。
  • 系统背景色会随环境变化。
  • 预览区域更接近真实系统界面。
  • transcript 中这一步的目的,是更容易看出 light/dark 差异。

11:11)主页面最后显示 Preview,而不是直接显示单个 ProgressView

Preview()

关键点:

  • Preview() 是自定义预览容器。
  • 它把多份 ProgressView 组织在一个 live view 里。
  • 这样主页面不用承载真实 app 入口。
  • 对 SwiftUI 原型来说,预览 view 本身就是测试夹具。

11:32)第二个 ProgressView 通过环境修饰符切到 dark mode。再次运行后,Playground 同时显示 light mode 和 dark mode。

.environment(\.colorScheme, .dark)

关键点:

  • .environment 改写子视图读取到的环境值。
  • \.colorScheme 指向颜色模式。
  • .dark 让其中一个预览以深色模式渲染。
  • 这能在一个 Playground 里并排检查两个外观。

让预览可交互

12:10)最后,演讲者用状态变量驱动进度值。live view 是 fully interactive,所以可以在 Playground 里点按钮观察动画。

@State var progress = 0.25

关键点:

  • @State 把进度保存在 SwiftUI view 内部。
  • 初始值 0.25 对应 25 percent。
  • 状态变化会驱动 view 重新渲染。
  • 这个变量随后传给两个 ProgressView

12:18)两个预览都使用同一个进度值。这样点击按钮时,light mode 和 dark mode 会一起更新。

ProgressView(progress)

关键点:

  • progress 是上一步的 state。
  • initializer 在单独文件中已经标记为 public。
  • 同一个输入可以驱动多个预览实例。
  • 这让不同环境下的表现保持可比较。

12:32)最小交互只是把进度加 25 percent。官方片段先给出没有动画的版本。

func increment() {
  self.progress += 0.25
}

关键点:

  • increment() 是按钮 action 会调用的方法。
  • self.progress += 0.25 每次增加四分之一。
  • 它直接修改 @State
  • 修改 state 后,SwiftUI 负责刷新依赖它的视图。

12:40)随后演讲者把同一行状态修改包进 withAnimation。这让进度变化带动画,而调用点不用改变。

func increment() {
  withAnimation {
    self.progress += 0.25
  }
}

关键点:

  • withAnimation 包住状态修改。
  • 动画附着在由该状态触发的视图变化上。
  • 原来的进度计算没有变化。
  • Playground live view 可以直接测试动画手感。

12:52)按钮使用 increment 作为 action。它把交互入口放进 preview,而不是等完整 app 写完再验证。

Button(action: increment)

关键点:

  • Button 是 SwiftUI 的交互控件。
  • action: increment 绑定上面的状态更新方法。
  • 按钮放在 VStack 中,和两个预览共用同一个 state。
  • transcript 中点击按钮后,ProgressView 会工作并播放动画。
Button(action: increment) {
  Text("Increment Progress")
}

关键点:

  • 这个片段给按钮加上文字 label。
  • Text("Increment Progress") 是按钮显示内容。
  • action 和 label 一起构成完整按钮。
  • 在 Playground 中点它,就能检查不同进度值下的视图表现。

核心启发

  • 做一个 SwiftUI 控件草稿板:做什么:把正在设计的单个 SwiftUI 控件放进 Xcode Playground,用 live view 单独运行。为什么值得做:session 展示了从 CircleZStackText 起步验证进度视图,比进入完整 app 流程更轻。怎么开始:创建 blank Xcode Playground,导入 SwiftUIPlaygroundSupport,用 PlaygroundPage.current.setLiveView 显示目标 view。

  • 做 light/dark 并排预览页:做什么:为关键组件写一个只用于预览的 Preview view,一次渲染多份组件。为什么值得做:演讲用 VStack.environment(\.colorScheme, .dark) 同时检查浅色与深色模式。怎么开始:把真实组件放到单独文件,主页面只保留 Preview()

  • 做交互状态试验台:做什么:给 preview 加 @State、按钮和动画,用来测试控件在不同输入值下的反馈。为什么值得做:session 结尾用 progress state 和 withAnimation 验证进度变化,不必先接入真实数据源。怎么开始:在预览 view 内声明 @State var progress,把它传进组件,再用 Button(action:) 修改它。

  • 做团队共享的 SwiftUI 调参 Playground:做什么:把颜色、间距、线宽等设计参数放进 Playground,让设计和开发一起试。为什么值得做:transcript 展示了颜色 literal、代码补全和 brace dragging,适合快速调整视觉细节。怎么开始:把设计中的几个候选值变成 Playground 里的 SwiftUI 片段,运行后截图或共享 Playground 文件。

关联 Session

评论

GitHub Issues · utterances