Highlight
第三方拍摄 App 现在可以从锁屏直接启动,用户通过控制中心、Action Button 或锁屏控件即可进入取景器拍照,无需先解锁设备。
核心内容
用户掏出手机拍照时,期望的是”按一下就拍”,而不是先解锁、再找 App、再等取景器加载。系统相机 App 一直可以在锁屏状态下直接使用,但第三方拍摄 App 没有这个能力——直到 iOS 18。
iOS 18 的 LockedCameraCapture 框架填补了这个缺口。它提供了一种新的 App Extension 类型——Locked Camera Capture Extension,让你的拍摄界面可以从控制中心、Action Button 或锁屏控件直接启动,无需解锁设备。用户操作路径从”解锁 → 找 App → 拍照”缩短为”按控制 → 直接拍”。
整个生命周期围绕”锁屏安全”设计:扩展启动后必须立即展示取景器,否则系统终止进程;拍摄完成后,内容通过 sessionContentURL 目录或 PhotoKit 保存;用户如需深度操作(比如分享到社交网络),扩展调用 openApplication 请求解锁并无缝跳转到主 App;扩展被 dismissed 后,session 内容自动迁移到主 App 的容器,扩展容器则被擦除。每一层都确保锁屏状态下的数据隔离。
详细内容
Locked Camera Capture Extension 的入口
扩展的入口是一个遵循 LockedCameraCaptureExtension 协议的 SwiftUI 结构体,body 返回 LockedCameraCaptureUIScene(11:21):
@main
struct ClownTownCaptureExtension: LockedCameraCaptureExtension {
var body: some LockedCameraCaptureUIScene {
LockedCameraCaptureUIScene { session in
CaptureView(session: session)
}
}
}
关键点:
@main标注这是扩展的入口点LockedCameraCaptureExtension是 iOS 18 新增的协议,Xcode 提供对应模板,包含取景器和快门按钮LockedCameraCaptureUIScene的初始化闭包接收一个LockedCameraCaptureSession对象,这是扩展与系统交互的核心
LockedCameraCaptureSession 提供的能力
Session 对象是扩展运行期间的中心枢纽,提供三个关键能力(12:41):
// 1. 持久化目录:保存拍摄数据的唯一推荐位置
let contentURL = session.sessionContentURL
// 2. 标记内容已处理完毕,系统可删除该目录
session.invalidateSessionContent()
// 3. 请求打开主 App(触发设备解锁)
session.openApplication(
NSUserActivity(activityType: NSUserActivityTypeLockedCameraCapture)
)
关键点:
sessionContentURL指向扩展容器中的一个目录,扩展被 dismissed 后唯一会被迁移到主 App 容器的内容就在这里- 扩展容器中的其他数据都会被擦除——不要把需要持久化的数据存到别处(08:46)
invalidateSessionContent()调用后,之前写入的内容会被删除,但目录本身仍可继续写入(13:38)openApplication只应在用户主动交互(如点击按钮)时调用,不能自动触发(13:51)
CameraCaptureIntent 与 Control 的配合
用户需要一个控件来启动你的扩展。这个控件由 WidgetKit 的 Control 实现,配合新的 CameraCaptureIntent(14:54):
struct ClownTownCaptureIntent: CameraCaptureIntent {
static var title: LocalizedStringResource = "ClownTown Capture"
// appContext 用于在 App 和扩展之间共享偏好设置
var clownTownContext: ClownTownContext?
func perform() async throws -> some IntentResult {
// 读取 context,设置扩展的初始状态
return .result()
}
}
关键点:
CameraCaptureIntent是 iOS 18 新增的 Intent 类型,专门用于启动拍摄扩展- Intent 必须同时包含在三个 target 中:Widget Extension、Capture Extension、主 App(15:17)
appContext是 App 和扩展之间共享状态的通道,但大小有限,过大会导致无法持久化(16:08)- 用
updateAppContext()更新共享状态,两边都能读到最新值(16:56)
主 App 端接收拍摄内容
主 App 通过 LockedCameraCaptureManager 获取扩展拍摄的内容(20:24):
let manager = LockedCameraCaptureManager.shared
// 获取所有待处理的 session 目录
let urls = manager.sessionContentURLs
// 异步监听新的 session 内容
for await update in manager.sessionContentUpdates {
switch update {
case .added(let url):
// 处理新到达的拍摄内容
processContent(at: url)
manager.invalidateContent(at: url)
case .removed(let url):
break
}
}
关键点:
sessionContentUpdates是一个 AsyncSequence,初始值包含所有已有的 session URL,之后持续监听新增和删除(20:53)- 从扩展过渡到 App 时,最新的 session 目录可能在 App 启动后才就绪,因此推荐用异步序列而非一次性读取(21:19)
invalidateContent(at:)调用后会删除该目录内容,同时触发.removed更新事件(21:27)
锁屏状态下的安全限制
扩展在锁屏状态下受到严格限制(05:34):
- 必须立即展示相机取景器,否则系统终止扩展
- 必须使用
AVCaptureEventInteraction处理硬件按钮事件(音量键拍照/录像) - 不能访问网络
- 不能读写 App 的共享 Group Container
- 不能访问 App 的 SharedPreferences
- PhotoKit 在锁屏下只允许读取当前 session 写入的照片和视频
核心启发
-
做什么:为现有拍摄 App 添加 Lock Screen 快捷入口。为什么值得做:用户拍照时的核心诉求是速度,锁屏直达能显著降低操作摩擦,让第三方 App 获得和系统相机同等的启动优先级。怎么开始:在 Xcode 中新建 Locked Camera Capture Extension target,先把已有的 SwiftUI 取景器视图复用进去,再逐步添加 Control 和 Intent。
-
做什么:利用 sessionContentURL 实现拍摄数据的离线安全存储。为什么值得做:扩展的网络和容器访问被禁止,但 session 目录在扩展 dismissed 后会自动迁移到主 App,这天然形成了一个”先拍后同步”的架构——拍摄时完全离线,App 运行时再上传。怎么开始:拍摄数据写入
session.sessionContentURL,在主 App 的LockedCameraCaptureManager.sessionContentUpdates中异步取出并处理。 -
做什么:用 appContext 在扩展和 App 之间同步用户偏好。为什么值得做:扩展无法访问共享容器和偏好设置,但用户在 App 中选择的滤镜、拍摄模式等设置需要延续到锁屏拍摄场景。怎么开始:在
CameraCaptureIntent的appContext中存储关键设置,扩展启动时从 context 读取,用户在扩展中修改设置时调用updateAppContext()写回。 -
做什么:设计”扩展拍摄 → 解锁跳转 → 深度编辑”的连贯工作流。为什么值得做:很多拍摄场景需要后续操作(加滤镜、分享、编辑),而扩展无法联网和访问完整资源,openApplication 提供了无缝过渡的能力。怎么开始:在扩展中为需要深度操作的按钮调用
session.openApplication(),通过NSUserActivity的 userInfo 传递上下文,主 App 在handleActivity中恢复到对应的 UI 状态。
关联 Session
- Extend your app’s controls across the system — 详解如何创建 Control Center、锁屏和 Action Button 上的自定义控件
- Design App Intents for system experiences — App Intents 驱动控件、Spotlight、Siri 等系统级体验的设计方法
- Keep colors consistent across captures — 拍摄场景下如何保持色彩一致性
- Use HDR for dynamic image experiences in your app — 在 App 中集成 HDR 图片和视频体验
- Build compelling spatial photo and video experiences — 创建沉浸式空间照片和视频体验
评论
GitHub Issues · utterances