将系统照片选择器嵌入你的 App
Embed the Photos Picker in your app
2023年6月5日
一句话判断
iOS 17 让你把系统的 Photos Picker 直接嵌入 App 界面,配合 continuous selection 模式实现实时选图,再也不需要自建相册浏览器。
这场 Session 讲了什么
Justin 从 Photos 团队出发,介绍了 Photos Picker 在 iOS 17 中的重大增强:
嵌入式选择器。之前 Photos Picker 只能以 modal sheet 方式弹出。iOS 17 新增 .photosPickerStyle(.inline) 修饰符,让它直接嵌入你的 SwiftUI 视图中。即使嵌入,它仍然在独立进程中渲染,App 无法直接访问未选中的照片。
三种样式。.presentation(默认的 sheet 模式)、.inline(嵌入模式,占满指定区域)、.compact(单行横向滚动模式,适合空间受限的 UI)。
连续选择。设置 selectionBehavior: .continuous 后,用户每次选择/取消选择都会实时通知 App,不需要点击”添加”按钮确认。这让嵌入模式下的体验变得非常流畅。
配件控制。可以隐藏导航栏、工具栏、搜索栏等 UI 元素,也可以禁用特定功能(如搜索、相册导航、暂存区),然后用你自己的 UI 替代。
隐私透明度。首次展示嵌入式选择器时,系统自动弹出说明 UI,告知用户 App 只能访问被选中的照片。选择器上有隐私徽章标识其独立进程属性。
值得深挖的点
独立进程渲染的边界。嵌入的选择器看起来像是你 App 的一部分,但它实际上运行在独立进程中。你的 App 不能截图选择器内容,不能程序化控制选择器的滚动或点击。只有用户主动选择的资产才会传递给你的 App。
compact 样式的使用场景。单行选择器适合消息输入框上方的附件栏、笔记 App 的插图区域等纵向空间有限但需要展示照片选项的 UI。
UIKit 和 AppKit 的对应 API。同样的能力通过 PHPickerConfiguration 提供,支持 selection: .continuous、mode: .compact、edgesWithoutContentMargins、disabledCapabilities 等属性。需要作为 child view controller 添加。
代码片段
// 嵌入式 Photos Picker 完整配置
PhotosPicker(
selection: $selectedItems,
matching: .images,
photoLibrary: .shared()
) {
// 自定义选择器触发按钮(presentation 模式)
Text("选择照片")
}
.photosPickerStyle(.inline) // 嵌入模式
.photosPickerAccessoryVisibility(.hidden, edges: .all) // 隐藏导航栏和工具栏
.photosPickerDisabledCapabilities(.selectionActions) // 隐藏取消和添加按钮
.ignoresSafeArea() // 让选择器扩展到屏幕底部边缘
.frame(height: 300) // 固定高度
// 连续选择模式:实时接收选中的照片
@State var selectedItems: [PhotosPickerItem] = []
@State var selectedImages: [UIImage] = []
// 使用 onChange 监听选择变化
.onChange(of: selectedItems) { newItems in
Task {
for item in newItems {
if let data = try? await item.loadTransferable(type: Data.self),
let image = UIImage(data: data) {
selectedImages.append(image)
}
}
}
}
最佳实践
- 用系统 Photos Picker 替代自建相册浏览器,获得搜索、缩放网格等免费功能。
- 嵌入模式配合 continuous selection 和隐藏配件按钮,可以实现完全定制的外观。
- compact 样式适合空间受限的 UI,但别忘了处理横向滚动的交互。
- 尊重隐私徽章和引导 UI 的展示,不要试图绕过它们。
- 处理 HDR 照片和 Cinematic 模式视频时,注意配置正确的
PHPickerConfiguration选项。
还有什么值得关注
- “What’s new in privacy” Session 讲了照片权限提示的变更
- 系统选择器支持搜索和缩放网格,这些功能不需要你自己实现
- UIKit/AppKit 的对应 API 让非 SwiftUI 项目也能使用嵌入模式
- 选择器自动处理 Safe Area,配合
.ignoresSafeArea()可以扩展到屏幕边缘