You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:51:02