SwiftUI的SignInWithAppleButton在tvOS上点击回调不触发如何解决?
问题根因
tvOS 平台的苹果登录授权流程要求必须提供明确的presentation context provider来指定登录弹窗的展示锚点,SwiftUI 原生的 SignInWithAppleButton 在 tvOS 14 及更低版本中存在适配缺陷,无法自动绑定当前窗口上下文,导致系统收到点击事件后无法初始化授权流程,因此不会触发任何回调也不会输出报错。
前置检查项
- 确认项目
Signing & Capabilities面板中已经添加 Sign In with Apple 能力 - 确认测试用 Apple TV 设备的系统日期时间正常,未开启代理或 VPN 拦截苹果服务请求
最优解决方案:使用 UIViewRepresentable 封装原生按钮
原生 ASAuthorizationAppleIDButton 可以完全控制授权流的上下文配置,适配性更强,示例代码如下:
import SwiftUI import AuthenticationServices struct TVSignInWithAppleButton: UIViewRepresentable { typealias UIViewType = ASAuthorizationAppleIDButton func makeUIView(context: Context) -> ASAuthorizationAppleIDButton { let button = ASAuthorizationAppleIDButton(type: .signIn, style: .whiteOutline) button.addTarget(context.coordinator, action: #selector(Coordinator.handleTap), for: .primaryActionTriggered) return button } func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator: NSObject, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding { @objc func handleTap() { let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] let authController = ASAuthorizationController(authorizationRequests: [request]) authController.delegate = self authController.presentationContextProvider = self authController.performRequests() } func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else { return } // 处理登录成功逻辑 print("登录成功,用户唯一标识:\(appleIDCredential.user)") } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { // 处理登录失败逻辑 print("登录失败:\(error.localizedDescription)") } // tvOS 强制要求实现的方法,返回当前应用的主窗口作为弹窗锚点 func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { return UIApplication.shared.windows.first { $0.isKeyWindow }! } } } // 业务页面调用示例 struct SignInView: View { var body: some View { VStack(spacing: 40) { Text("Welcome to My App") .font(.system(size: 50.0, weight: .bold)) TVSignInWithAppleButton() .frame(width: 300, height: 50) } } }
高版本兼容方案(仅适用 tvOS 15+)
如果项目最低支持版本为 tvOS 15+,无需替换按钮,只需在原有 SignInWithAppleButton 所在的 View 层级绑定 presentationContext 即可:
SignInWithAppleButton(.signIn) { request in request.requestedScopes = [.fullName, .email] } onCompletion: { result in print(result) } .signInWithAppleButtonStyle(.whiteOutline) .frame(width: 300, height: 50) .presentationContext { context in return UIApplication.shared.windows.first { $0.isKeyWindow }! }
内容的提问来源于stack exchange,提问作者Scott Andrew
相关产品推荐
相关产品推荐

