Simplify sign in for your tvOS apps
System & Services 进阶 13m

简化 tvOS App 的登录体验

Simplify sign in for your tvOS apps

2021年6月8日

在 Apple 官方观看视频

一句话判断

tvOS 上输入密码是一种酷刑——支持 iPhone 自动填充登录是你的 App 用户体验的底线要求,不是加分项。

这场 Session 讲了什么

这个 Session 聚焦在 tvOS 上最让人头疼的问题:登录。Apple TV 没有触摸屏,遥控器打字体验很差,任何需要用户输入用户名和密码的步骤都会大幅降低转化率。iOS 15 和 tvOS 15 提供了多种方案来简化这个过程。

Session 介绍了三种主要的简化方案:一是「通过 iPhone 认证」——用户在 Apple TV 上点击登录后,iPhone 上会弹出通知,直接用 Face ID/Touch ID 完成认证,不需要在 TV 上输入任何东西。这是基于 ASAuthorizationController 的 Sign in with Apple 能力的扩展。二是 iCloud Keychain 密码自动填充——用户在 iOS 上保存的密码可以通过 iCloud 同步到 tvOS,在输入框中自动提示。三是 VPN App 的快速配置——tvOS 15 新增了 NETunnelProviderManager 的配置推送能力,用户可以在 iPhone 上配置好 VPN 然后一键推送到 Apple TV。

对于大多数 tvOS 开发者来说,Session 的核心建议很明确:如果你的 App 需要登录,必须支持至少一种免输入方案。

值得深挖的点

ASAuthorizationController 在 tvOS 上的跨设备流程。 tvOS 上的 Sign in with Apple 有一个特殊的「跨设备」模式:当你在 Apple TV 上发起登录请求时,系统会通过 iCloud 通知用户的 iPhone 或 iPad,用户在移动设备上完成 Face ID 验证后,认证结果自动回传给 Apple TV。整个过程用户不需要在 TV 上做任何操作。实现方式是使用 ASAuthorizationControllerperformRequests() 方法,tvOS 上会自动触发跨设备流程。你的 App 需要处理 authorizationController(controller:didCompleteWithAuthorization:) 回调来获取 credential。

iCloud Keychain 在 tvOS 上的自动填充机制。 tvOS 15 支持在 UITextField 中自动填充 iCloud Keychain 里保存的密码。当你的 tvOS App 的输入框获得焦点时,如果 Keychain 中有匹配当前域名的账号密码,系统会在输入框下方显示提示。用户只需要用遥控器选择即可完成填充,不需要用遥控器逐字输入。前提是你在 App 的 Associated Domains 中配置了正确的域名,并在服务端部署了 apple-app-site-association 文件。

代码片段

import AuthenticationServices

// tvOS 上使用 Sign in with Apple 的跨设备认证
class SignInViewController: UIViewController {

    func startSignIn() {
        let request = ASAuthorizationAppleIDProvider().createRequest()
        request.requestedScopes = [.fullName, .email]

        let controller = ASAuthorizationController(authorizationProvider: ASAuthorizationAppleIDProvider(),
                                                    requests: [request])
        controller.delegate = self
        controller.performRequests()
        // tvOS 上会自动在用户的 iPhone/iPad 上弹出认证通知
    }
}

extension SignInViewController: ASAuthorizationControllerDelegate {
    func authorizationController(controller: ASAuthorizationController,
                                  didCompleteWithAuthorization authorization: ASAuthorization) {
        // 获取用户 credential,登录成功
        let credential = authorization.credential as? ASAuthorizationAppleIDCredential
        let userId = credential?.user
        let identityToken = credential?.identityToken
    }
}
// 在 tvOS 的 UITextField 中启用密码自动填充
let usernameField = UITextField()
usernameField.textContentType = .username

let passwordField = UITextField()
passwordField.textContentType = .password
passwordField.isSecureTextEntry = true

// Keychain 中的密码会自动出现在输入建议中
// 检查用户是否已经通过 Sign in with Apple 登录过
func checkExistingSignIn() {
    let provider = ASAuthorizationAppleIDProvider()
    provider.getCredentialState(forUserID: storedUserId) { state, error in
        switch state {
        case .authorized:
            // 用户已登录,直接进入 App
            break
        case .revoked, .notFound:
            // 需要重新登录
            break
        default:
            break
        }
    }
}

最佳实践

  • tvOS App 的登录流程必须支持至少一种免输入方案(Sign in with Apple 或 iCloud Keychain),否则用户流失率会非常高
  • 如果你同时提供 Sign in with Apple 和传统用户名/密码登录,把 Sign in with Apple 放在登录界面的最显眼位置
  • 测试跨设备认证时,确保 Apple TV 和 iPhone 登录了同一个 iCloud 账号,且两台设备都连接到了互联网
  • 对于付费内容 App(视频、音乐),考虑在用户首次打开时就引导登录,而不是等到用户想看内容时才弹出

还有什么值得关注

  • tvOS 15 还支持通过 iPhone 配置 Apple TV 的网络设置(包括 VPN),通过 NETunnelProviderManager 实现
  • UISimpleTextInput 在 tvOS 上可以接收来自 iPhone 的键盘输入,这是另一个减少 TV 端输入的方案
  • 用户可以在「设置 > 用户和账户」中管理所有 tvOS App 的登录状态,App 应该正确响应 credential state 的变化
WWDC 2021