在 tvOS 应用中支持多用户
Support multiple users in tvOS apps
2022年6月6日
一句话判断
如果你的 tvOS 流媒体应用还在让每个家庭成员手动选择 profile,tvOS 16 的新 API 可以让这一切自动化——切换系统用户后应用自动切换到对应的 profile。
这场 Session 讲了什么
tvOS 团队的 Felipe 详细讲解了 tvOS 16 中多用户支持的新特性。Apple TV 是家庭共享设备,不同家庭成员应该看到各自个性化的内容。Session 介绍了两个关键新功能:控制中心现在可以显示 iCloud 家庭成员(即使他们还没添加到 Apple TV),以及新的用户无关 Keychain API。
核心场景是流媒体应用的 profile 管理:当一个家庭的多个人使用同一台 Apple TV 时,应用应该能自动识别当前系统用户并加载对应的 profile,而不是每次都弹出 profile 选择器。
Session 还演示了 “Runs as Current User” entitlement 配合新 Keychain API的完整工作流:每个用户有独立的 UserDefaults,但共享同一个登录凭证。
值得深挖的点
“Runs as Current User” 的精妙设计。 在 Xcode 中添加 User Management capability 后,勾选 “Runs as Current User”,应用的进程就会以当前系统用户身份运行。所有数据(包括 Keychain、UserDefaults)自动按用户隔离,不需要改一行代码。这对游戏类应用尤其友好——每个人的进度自动分离。
用户无关 Keychain 解决了登录问题。 “Runs as Current User” 默认会让 Keychain 也按用户隔离,这意味着每个家庭成员都要单独登录。新引入的 kSecUseUserIndependentKeychain 属性打破了这一限制——设置为 true 后,存储的凭证对所有用户可见,实现一次登录全家使用。
家庭用户添加流程的简化。 tvOS 16 的控制中心现在显示 iCloud 家庭成员列表,未添加的成员以 ”+” 图标标识。选择后,只需将 iPhone 靠近 Apple TV 并在 iPhone 上确认即可完成添加。
TVUserManager 的手动映射被废弃。 以前需要手动维护系统用户到应用 profile 的映射关系,tvOS 16 中这些 API 被标记为废弃。现在系统自动处理用户与数据的关联。
代码片段
import Security
// 使用用户无关 Keychain 存储登录凭证
func saveCredentials(username: String, password: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: username,
kSecValueData as String: password.data(using: .utf8)!,
// 关键:设置为用户无关 Keychain
kSecUseUserIndependentKeychain as String: true
]
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { return }
}
// 读取用户无关 Keychain 中的凭证
func readCredentials() -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecMatchLimit as String: kSecMatchLimitOne,
kSecReturnData as String: true,
// 读取时也需要指定用户无关 Keychain
kSecUseUserIndependentKeychain as String: true
]
var result: AnyObject?
SecItemCopyMatching(query as CFDictionary, &result)
guard let data = result as? Data else { return nil }
return String(data: data, encoding: .utf8)
}
// 每个用户的 profile 选择存储在 UserDefaults 中
// "Runs as Current User" 下 UserDefaults 自动按用户隔离
func saveSelectedProfile(_ profileId: String) {
UserDefaults.standard.set(profileId, forKey: "selectedProfile")
}
最佳实践
- 为你的 tvOS 应用启用 “Runs as Current User” entitlement,让数据自动按用户隔离
- 登录凭证使用
kSecUseUserIndependentKeychain存储到用户无关 Keychain,实现单次登录 - 每个用户的 profile 选择等个性化设置存储在 UserDefaults 中,系统自动隔离
- 结合 tvOS 15 的 iPhone 辅助登录功能,以及 tvOS 16 新增的 OAuth 和 Passkey 支持,进一步简化登录流程
- 不再需要手动维护 TVUserManager 的用户映射关系,依赖系统的自动用户关联
- iOS 端的代码可以直接在 tvOS 上运行,UserDefaults 和 Keychain 的 API 完全一致
还有什么值得关注
- Shared iPad 也支持类似的多用户模型,这套方案可以跨平台复用
- OAuth 和 Passkey 在 tvOS 16 上的支持让第三方登录更加便捷
- 如果你的应用是纯游戏类(不需要共享登录),直接开启 “Runs as Current User” 即可,无需额外处理
- 配套观看 WWDC 2021 的 “Simplify sign-in for your tvOS apps” 了解 iPhone 辅助登录的实现细节