79827575

Date: 2025-11-22 21:45:28
Score: 1
Natty:
Report link

First of all, this is by no means a perfect example, but rather an idea of how it can be implemented. For example, to make it easier to show, I am using @AppStorage and the ID to save it here.

I had the same Issue today, … in tvOS, the SignInWithAppleButton does not trigger its closures. It only renders the required visual appearance of the button and haptics/animations.

How to fix this?

I used the official SignInWithAppleButton and attached an .onTapGesture that launches a custom ASAuthorizationController with my own ASAuthorizationControllerDelegate, as the button does not trigger its built-in request or completion handlers under tvOS.

Example (the Button)

SignInWithAppleButton { _ in } onCompletion: { _ in }
.onTapGesture {
    Task { await viewModel.signInWithApple() }
}

Example ViewModel

import Combine
import SwiftUI

@MainActor
class ViewModel: ObservableObject {
    
    @AppStorage("signInWithAppleUserIdString") var signInWithAppleUserIdString: String = ""
    var appleSignInManager = AppleSignInManager()
   
    func signInWithApple() async {
        let appleIdString = await appleSignInManager.signIn()
        
        if let appleIdString {
            signInWithAppleUserIdString = appleIdString
        } else {
            print("ERROR: USER NOT SIGNED IN WITH APPLE")
        }
    }
    
    func signOutFromApple() {
        signInWithAppleUserIdString = ""
    } 
}

Example Class
I called it AppleSignInManager because it's simple, but that's roughly how you could create it.

import AuthenticationServices
import Combine
import SwiftUI

@MainActor
final class AppleSignInManager: NSObject, ObservableObject,
                                ASAuthorizationControllerDelegate,
                                ASAuthorizationControllerPresentationContextProviding {

    private var continuation: CheckedContinuation<String?, Never>?

    override init() {
        super.init()
    }

    func signIn() async -> String? {
        return await withCheckedContinuation { continuation in
            self.continuation = continuation
            startAuthorization()
        }
    }

    private func startAuthorization() {
        let provider = ASAuthorizationAppleIDProvider()
        let request = provider.createRequest()
        request.requestedScopes = []

        let controller = ASAuthorizationController(authorizationRequests: [request])
        controller.delegate = self
        controller.presentationContextProvider = self
        controller.performRequests()
    }

    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {

        if let keyWindow = UIApplication.shared.connectedScenes
            .compactMap({ $0 as? UIWindowScene })
            .flatMap({ $0.windows })
            .first(where: { $0.isKeyWindow }) {
            return keyWindow
        }

        if let windowScene = UIApplication.shared.connectedScenes
            .compactMap({ $0 as? UIWindowScene })
            .first {
            return ASPresentationAnchor(windowScene: windowScene)
        }

        fatalError("NO WINDOW SCENE FOUND")
    }

    func authorizationController(controller: ASAuthorizationController,
                                 didCompleteWithAuthorization authorization: ASAuthorization)  {

        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential {
            let userId = credential.user
            continuation?.resume(returning: userId)
            continuation = nil
        } else {
            continuation?.resume(returning: nil)
            continuation = nil
        }
    }

    func authorizationController(controller: ASAuthorizationController,
                                 didCompleteWithError error: Error) {

        print("ERROR:", error.localizedDescription)
        continuation?.resume(returning: nil)
        continuation = nil
    }
}

Explanation

My ViewModel stores the user ID returned by the “Sign in with Apple” authorization process and is directly linked to the custom ASAuthorizationControllerDelegate, which provides the result.

Reasons:
  • Whitelisted phrase (-1): I had the same
  • RegEx Blacklisted phrase (1.5): How to fix this?
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • User mentioned (1): @AppStorage
  • Low reputation (0.5):
Posted by: SomeUser