Highlight
tvOS 14 的 User Management capability 新增 Runs as Current User,应用声明支持后会以当前 Apple TV 用户的 iCloud、Game Center 和本地存储运行,并在用户切换时由系统终止后重新启动。
核心内容
Apple TV 放在客厅里,天然会被一家人共用。tvOS 13 已经把用户切换放进 Control Center,也提供了 TVUserManager,让有自建账号体系的 app 可以把应用内 profile 关联到设备用户。但很多 app 没有自己的 profile。它们只想把 iCloud、Game Center、本地数据和偏好设置按家庭成员分开。
以前这类 app 面对的是一套全设备共享资源。一个游戏的进度、成就、好友列表和本地设置,都会落在同一个应用环境里。用户切换了 Apple TV 账号,app 仍然可能展示上一个人的棋盘、历史记录或高分。
tvOS 14 给出的解法是 Runs as Current User。开发者在 Xcode 12 的 Signing & Capabilities 里添加 User Management capability 后,系统会把 app 绑定到当前选中的 Apple TV 用户。这个用户会拿到自己的 iCloud、Game Center、本地数据和偏好设置。
这个能力的关键在生命周期。用户在 Control Center 切换账号时,系统会给正在运行的 app 一个很短的保存窗口,然后终止进程。如果 app 当时在前台,系统会为新用户重新启动它。原有的读写 API 仍然可用,数据隔离由系统完成。
session 的演示是一个用 NSPersistentCloudKitContainer 同步数据的小游戏。接入能力前,Felipe 切到自己的用户后仍然看到 Caleb 的棋盘。接入能力后,切换会触发终止和重新启动,Felipe 看到自己的空棋盘和 39 秒高分,Caleb 的 1 分 09 秒记录不会混在一起。
详细内容
打开 Runs as Current User
(03:12)接入从 Xcode 12 开始。进入 app target 的 Signing & Capabilities,添加 User Management capability,新的 Runs as Current User 选项会默认选中。
这个声明告诉系统:app 希望按当前 Apple TV 用户运行。声明生效后,app 访问 iCloud、Game Center、本地存储和偏好设置时,系统会把这些资源映射到当前用户。session 明确说明,已有的存储 API 可以继续使用,开发者不用为了数据隔离重写读写逻辑。
关键点:
User Management是能力入口,位置在 Xcode 的 Signing & Capabilities。Runs as Current User是 tvOS 14 新选项,Xcode 12 添加能力时会默认选中。- 当前用户切换后,app 拿到的是新用户的账号和存储上下文。
- iCloud、Game Center、本地数据和 preferences 都属于这套隔离范围。
在用户切换前保存数据
(03:46)用户切换时,正在运行的 app 会被终止。app 需要在 applicationWillTerminate 里做最少量的保存工作,避免棋盘、进度或本地更改丢失。
func applicationWillTerminate(_ application: UIApplication) {
guard game.hasUnsavedChanges else { return }
let semaphore = DispatchSemaphore(value: 0)
game.save { _ in semaphore.signal() }
semaphore.wait()
}
关键点:
applicationWillTerminate是系统给 app 的最后保存机会。guard game.hasUnsavedChanges else { return }没有改动时立刻返回,让用户切换继续。game.save把未保存数据写到本地和 CloudKit,符合演示中游戏同步数据的场景。DispatchSemaphore让异步保存有时间完成,但 session 也提醒这里的时间有限,工作量要尽量小。
丢弃其他用户的 CloudKit 通知
(04:46)支持多用户后,同一台 Apple TV 上用过 app 的其他用户也可能产生 CloudKit subscription notifications。app 收到通知时,需要检查通知所属用户是否等于当前 CloudKit 用户。
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
if let notification = CKNotification(fromRemoteNotificationDictionary: userInfo),
notification.subscriptionOwnerUserRecordID == game.currentUserRecordID {
game.handle(notification, completionHandler: completionHandler)
}
else {
completionHandler(.noData)
}
}
关键点:
CKNotification(fromRemoteNotificationDictionary:)从推送 payload 还原 CloudKit 通知。subscriptionOwnerUserRecordID是 session 提到的新检查点,用来识别订阅所属用户。game.currentUserRecordID代表当前运行上下文里的 CloudKit 用户。- 两个 record ID 相等时才处理通知,避免把别人的同步事件应用到当前用户界面。
- 不属于当前用户的通知直接调用
completionHandler(.noData),让系统知道没有可处理数据。
用演示验证数据隔离
(05:59)演示项目先展示未接入能力时的问题:Caleb 的游戏进度和高分仍然停留在屏幕上,Felipe 切换用户后没有看到自己的数据。
(06:47)接入步骤只有三步:打开 app target,添加 User Management capability,确认 Runs as Current User 已选中。重新运行后,用户切换会终止旧进程,系统再为 Felipe 重新启动游戏。
(07:30)重新启动后的游戏读取 Felipe 自己的数据。他没有未完成棋盘,所以主菜单显示开始新游戏;他的最快成绩是 39 秒。Caleb 的 1 分 09 秒成绩仍然保留在 Caleb 的用户环境里。
关键点:
- 这套机制适合没有自建 profile 的 app。
- 使用
NSPersistentCloudKitContainer的 app 可以继续让数据跨 iPhone、Apple TV 和其他设备同步。 - app 仍然要处理终止前保存和 CloudKit 通知归属检查。
核心启发
-
家庭游戏的独立进度
- 做什么:让同一台 Apple TV 上的每个家庭成员拥有独立的存档、高分和 Game Center 数据。
- 为什么值得做:session 的演示证明,Runs as Current User 可以把 iCloud、Game Center 和本地数据按当前用户隔离。
- 怎么开始:添加 User Management capability,确认 Runs as Current User 已启用,再在
applicationWillTerminate中保存未完成棋盘。
-
跨设备继续玩的 tvOS 版本
- 做什么:用户在 iPhone 开始游戏,回到客厅后在 Apple TV 上继续同一局。
- 为什么值得做:transcript 明确提到,每个人可以访问自己的 iCloud 数据,并在 Apple TV 与其他设备之间同步进度。
- 怎么开始:沿用现有 iCloud 或
NSPersistentCloudKitContainer数据层,把 tvOS app 配置为当前用户运行。
-
面向家庭的视频继续观看
- 做什么:为同一个视频 app 保存每个用户自己的播放位置、最近观看和偏好设置。
- 为什么值得做:tvOS 14 会为当前用户提供独立的本地数据和 preferences,适合客厅共享设备。
- 怎么开始:先接入 User Management capability,再把现有“继续观看”数据写到当前 app 存储中,用户切换时让系统重新启动 app。
-
CloudKit 通知的用户隔离
- 做什么:只处理属于当前 CloudKit 用户的订阅通知。
- 为什么值得做:多用户 Apple TV 上,同一 app 可能收到其他用户留下的 CloudKit 通知。
- 怎么开始:收到远程通知后读取
subscriptionOwnerUserRecordID,只在它等于当前用户 record ID 时更新界面或数据。
关联 Session
- Build SwiftUI apps for tvOS — 继续完善 tvOS app 的布局、焦点、按钮和上下文菜单。
- Discover search suggestions for Apple TV — 为 Apple TV app 增加搜索建议和更好的遥控器输入体验。
- Master Picture in Picture on tvOS — 给 tvOS 视频 app 添加画中画播放和自定义播放界面。
- Tap into Game Center: Dashboard, Access Point, and Profile — 深入 Game Center 的认证、dashboard、access point 和玩家 profile。
- Sync a Core Data store with the CloudKit public database — 理解 Core Data 与 CloudKit 同步流程,补足跨设备数据层。
评论
GitHub Issues · utterances