WWDC Quick Look 💓 By SwiftGGTeam
Prototype with Xcode Playgrounds

Prototype with Xcode Playgrounds

观看原视频

Highlight

Xcode 15 的 Playgrounds 支持自动运行、内联结果展示和自定义类型描述,开发者可以在不重建项目的情况下快速原型化新功能,将迭代时间从分钟级降到秒级。

核心内容

你有一个功能想法,但每次修改都要重新编译、启动 App、导航到对应页面才能看到效果。这个循环可能要几分钟,灵感早就凉了。

Xcode Playgrounds 可以打破这个循环。把它加到项目里,直接调用项目中的类型,修改代码后秒级看到结果。

02:34)演讲者正在开发一个野生动物摄影 App,想给 checklist 增加筛选功能。列表里有 2000 多种鸟类,全部显示没有成就感。他需要在 birdsToShow 计算属性里加过滤逻辑。

直接在项目里新建 Playground(File > New > Playground),选择 Blank。项目中的 Playground 默认启用两个设置:

  • Build Active Scheme:每次执行前自动构建活跃 scheme
  • Import App Types:自动导入 app target 模块

这意味着 Playground 里可以直接使用项目中定义的 BirdProviderBird 等类型,不需要手动 import。

03:15)把运行模式切换到 “Automatically run”,停止输入后 Playground 自动执行。现在可以开始实验了。

内联结果与类型探索

04:05)声明一个 BirdProvider 实例:

let birdProvider = BirdProvider(region: .northAmerica)

Xcode 15 右侧结果栏显示这行代码的输出。点击内联结果切换按钮,可以看到详细结构:

  • birds 数组
  • region 枚举值

每行还有类型信息标签,tooltip 显示类型的来源模块。展开数组时,Xcode 15 会高亮产生该结果的源代码,方便对应。

05:45)默认情况下,自定义类型 Bird 的数组元素只显示索引号。让 Bird 遵循 CustomStringConvertible

extension Bird: CustomStringConvertible {
    public var description: String {
        return "\(commonName) (\(scientificName))"
    }
}

关键点:

  • description 返回常见名和科学名的组合
  • 这个扩展加在定义 Bird 的源文件中,debugger 也能受益
  • 遵循后,Playground 结果栏直接显示鸟的名称,不需要展开

07:53)如果想在点击行时显示鸟的相片,用 CustomPlaygroundDisplayConvertible

extension Bird: CustomPlaygroundDisplayConvertible {
    public var playgroundDescription: Any {
        return photo as Any
    }
}

关键点:

  • playgroundDescription 只在 Playground 环境中生效
  • 显式转成 Any 避免编译器警告 optional 信息丢失
  • 返回 nil 时,Playground 会回退到默认展示
  • Xcode 15 用分屏视图同时显示对象结构和预览

过滤与验证 UI

09:35)先过滤出还没有照片的鸟:

let birdsToFind = birdProvider.birds.filter { $0.photo == nil }

结果还有 1800 多只。再按科过滤,只看猫头鹰:

let owlsToFind = birdsToFind.filter { $0.family == .owls }

只剩 5 只,范围合理了。

11:15)验证自定义 ChecklistView

let checklist = ChecklistView()
for bird in owlsToFind {
    checklist.add(bird)
}

Xcode 15 的 Value History 模式用分屏视图展示每次循环迭代后的 UI 状态。演讲者发现表头在只有一只鸟时仍然显示复数 “birds”。

12:16)在 String Catalog 里给这个词添加复数变体(Vary By Plural),修改单数形式为 “bird”。回到 Playground,表头正确显示单复数形式。

集成外部依赖

14:27)演讲者想集成 BirdSightings 包来获取最近的观鸟记录。这个包自带文档 Playground,展示了 API 用法:

let barnOwlCode = "BNOW"
let centralParkLocation = CLLocationCoordinate2D(latitude: 40.785091, longitude: -73.968285)

let sightingsProvider = SightingsProvider()
sightingsProvider.fetchSightings(of: barnOwlCode, around: centralParkLocation)

在自己的 Playground 里实验:

import CoreLocation
import BirdSightings

let bird = owlsToFind.first!
let appleParkLocation = CLLocationCoordinate2D(latitude: 37.3348655, longitude: -122.0089409)

let sightingsProvider = SightingsProvider()
let sightings = sightingsProvider.fetchSightings(of: bird.speciesCode, around: appleParkLocation)

let mostRecentSighting = sightings.first
let sightingMapView = SightingMapView(sighting: mostRecentSighting)

18:55)用 Live View 查看地图效果:

import PlaygroundSupport
PlaygroundPage.current.liveView = sightingMapView

发现地图定位到了错误的位置。用 Xcode 15 改进的 CLLocationCoordinate2D 预览检查坐标,发现经度少了负号。修正后地图正确显示 Apple Park 附近。

22:20)把验证过的代码搬回项目:

func sightingToShow(for bird: Bird) -> Sighting? {
    let sightingsProvider = SightingsProvider()
    let sightings = sightingsProvider.fetchSightings(of: bird.speciesCode, around: lastCurrentLocation)
    let mostRecentSighting = sightings.first
    return mostRecentSighting
}

详细内容

Playground 执行模式

Xcode 15 提供两种执行模式:

  • Automatically run:停止输入后自动执行,适合快速实验
  • Manually run:手动控制执行时机,适合包含网络请求等耗时操作的情况

切换方式:长按底部运行按钮,从菜单选择。

多表达式行的新控件

09:48)当一行有多个表达式时,Xcode 15 显示新的侧边栏注释。点击控件可以看到每个表达式的独立结果。悬停在内联结果切换按钮上时,高亮对应的源代码范围。

从 Playground 到项目的代码迁移

Playground 里验证过的代码可以直接复制到项目中。需要注意:

  • Playground 里可以用 ! 强制解包,项目代码需要 proper error handling
  • 网络请求在 Playground 里手动执行,项目里要考虑异步和 loading 状态
  • Playground 的 Sources 目录里的扩展只在 Playground 内生效

核心启发

  • 做什么:给项目加一个 “Scratch” Playground,专门用来实验新算法和 API

  • 为什么值得做:不用重建项目、不用写临时测试代码,秒级看到结果。想法验证成本趋近于零

  • 怎么开始:File > New > Playground,选择 Blank,确保 Build Active Scheme 和 Import App Types 已勾选

  • 做什么:为项目中的核心模型类型实现 CustomStringConvertible

  • 为什么值得做:Playground 结果栏、debugger、print 都会显示有意义的描述,调试效率大幅提升

  • 怎么开始:给最常用的 3-5 个模型类型加 description 属性,返回业务上有意义的字符串

  • 做什么:用 Playground 验证第三方包的 API 再集成到项目

  • 为什么值得做:包的文档 Playground 或自己写的实验代码,能快速理解 API 的输入输出,避免在项目中反复编译调试

  • 怎么开始:import 包到 Playground,用真实参数调用关键 API,观察返回值的结构和内容

  • 做什么:用 Live View 预览复杂的自定义 UI 组件

  • 为什么值得做:MapView、Chart 等复杂组件在模拟器里查看成本高。Live View 提供全尺寸交互预览

  • 怎么开始:创建 UI 组件实例,设置 PlaygroundPage.current.liveView,在 Editor Options 中打开 Live View

关联 Session

评论

GitHub Issues · utterances