使用 Xcode Playgrounds 探索包和项目
Explore Packages and Projects with Xcode Playgrounds
2020年6月23日
一句话判断
Xcode 12 的 Playgrounds 终于可以直接打开 Swift Package 和 Xcode Project 了,这意味着你可以在不修改项目代码的情况下快速验证 API 和原型功能。
这场 Session 讲了什么
Xcode Playgrounds 一直是一个快速实验 Swift 代码的好工具,但过去它和实际项目之间有一道鸿沟——你不能直接在 Playground 中引用项目里的代码。Xcode 12 打通了这层隔阂。
现在你可以创建一个 Playground,直接嵌入到 Xcode Project 或 Swift Package 中。Playground 可以访问同一个项目里的所有源文件和依赖。Session 演示了三个使用场景:第一,在 Playground 中快速测试 Package 中的新 API,不需要写完整的测试用例。第二,在 Playground 中预览 SwiftUI 视图,实时查看 UI 变化。第三,利用 Playground 来学习和探索第三方 Package 的 API,不需要先创建一个完整的示例项目。
值得深挖的点
Playground 与 Swift Package 的集成
这是本次更新最实用的功能。当你在 Swift Package 目录下创建 Playground 时,Package 中的所有 public API 都可以直接使用。你不需要手动 import 源文件,也不需要复制代码。Playground 会自动编译 Package 并链接到 Playground 的执行环境中。这对 Package 开发者来说是一个巨大的效率提升——写一个新功能后,立刻在 Playground 里试验,不用写 Demo App。
增量编译与性能
Xcode 12 优化了 Playground 的编译性能。当 Playground 嵌入到项目中时,它会利用项目的编译缓存,而不是从头开始编译。这意味着第一次打开 Playground 可能稍慢(需要编译依赖),但后续的修改和运行几乎是即时的。
代码片段
在 Swift Package 中创建 Playground
场景:为一个网络请求 Package 创建 API 实验 Playground。
// 在 Package 目录下创建 Playground 文件
// 目录结构:
// MyNetworkPackage/
// ├── Package.swift
// ├── Sources/
// │ └── MyNetworkPackage/
// │ └── NetworkClient.swift
// └── Playgrounds/
// └── APIExperiment.playground
// Playground 中可以直接 import Package
import MyNetworkPackage
import Foundation
// 直接使用 Package 中的 API
let client = NetworkClient(baseURL: "https://api.example.com")
// 实验新的请求方法
client.request(endpoint: "/users") { result in
switch result {
case .success(let data):
print("收到数据: \(data.count) 字节")
case .failure(let error):
print("请求失败: \(error)")
}
}
在项目中用 Playground 预览 SwiftUI
场景:快速迭代 SwiftUI 组件的样式。
import SwiftUI
import PlaygroundSupport
// 假设这是你项目中的自定义组件
struct CustomCard: View {
let title: String
let subtitle: String
var isSelected: Bool = false
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(title)
.font(.headline)
.foregroundColor(isSelected ? .white : .primary)
Text(subtitle)
.font(.subheadline)
.foregroundColor(isSelected ? .white.opacity(0.8) : .secondary)
}
.padding()
.background(
RoundedRectangle(cornerRadius: 12)
.fill(isSelected ? Color.blue : Color(.systemGray6))
)
}
}
// 在 Playground 中实时预览
let card = CustomCard(
title: "WWDC 2020",
subtitle: "探索 Xcode 的新功能",
isSelected: true
)
PlaygroundPage.current.liveView = UIHostingController(rootView: card)
用 Playground 探索第三方 Package
场景:在 Playground 中试验 Alamofire 的用法。
// 在 Package.swift 中添加 Alamofire 依赖
// .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.0.0")
import Alamofire
// 快速测试 API 请求
AF.request("https://httpbin.org/get").responseJSON { response in
switch response.result {
case .success(let value):
print("响应数据: \(value)")
case .failure(let error):
print("请求出错: \(error)")
}
}
// 测试不同的 HTTP 方法
let parameters: [String: String] = [
"username": "testuser",
"message": "来自 Playground 的测试"
]
AF.request("https://httpbin.org/post",
method: .post,
parameters: parameters).responseJSON { response in
debugPrint(response)
}
用 Playground 做算法原型
场景:在引入新算法到项目之前先在 Playground 中验证。
// 实验一个新的排序算法
func quickSort<T: Comparable>(_ array: [T]) -> [T] {
guard array.count > 1 else { return array }
let pivot = array[array.count / 2]
let less = array.filter { $0 < pivot }
let equal = array.filter { $0 == pivot }
let greater = array.filter { $0 > pivot }
return quickSort(less) + equal + quickSort(greater)
}
// 验证正确性
let testInput = [5, 3, 8, 1, 9, 2, 7, 4, 6]
let result = quickSort(testInput)
print("排序结果: \(result)")
assert(result == testInput.sorted(), "排序结果不正确")
// 测量性能
import Foundation
let largeArray = Array(1...10000).shuffled()
let start = Date()
let _ = quickSort(largeArray)
let elapsed = Date().timeIntervalSince(start)
print("排序 10000 个元素耗时: \(String(format: "%.3f", elapsed * 1000))ms")
最佳实践
已有项目:在你的项目目录下创建一个 Playgrounds 文件夹,放几个常用的 Playground 文件。比如一个用于测试 API 响应格式,一个用于试验 UI 组件样式,一个用于验证算法正确性。这些 Playground 会跟随项目一起版本管理,团队成员都可以用。
新项目:把 Playground 作为开发流程的一部分。写新功能前先在 Playground 里实验 API 用法和边界情况,确认方案可行后再集成到项目代码中。这比直接写代码再反复编译运行要高效得多。
还有什么值得关注
- Playground 支持 markdown 注释(
//:开头的行),可以创建带文档的交互式教程。 - 在 Playground 中可以直接调试 Package 的 internal API(同 Module 内访问),这在 Test 中是做不到的。
- 建议把 Playground 纳入
.gitignore的例外列表,确保团队共享实验环境。