Home > OS >  SwiftUI return Bool from authorizationController async
SwiftUI return Bool from authorizationController async

Time:02-02

How could I return a Bool from this sign in with apple function that uses the authorizationController? I have been looking at withCheckedThrowingContinuation but with no luck. I have also seen some examples of using completion handlers but I would like to use async.

func signInWithApple(withState state: SignInState) async -> Bool {
    let request = signInWithAppleRequest(withState: state)
    let authorizationController = ASAuthorizationController(authorizationRequests: [request])
    authorizationController.delegate = self
    authorizationController.performRequests()
}

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
    
    //...
        
        let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce)
        
        switch state {
        case .signIn:
            Task {
                authenticationState = .authenticating
                do {
                    let result = try await Auth.auth().signIn(with: credential)
                    if result.additionalUserInfo?.isNewUser == true {
                        self.isNewUser = true
                    }
                    return true
                } catch {
                    self.authenticationState = .unauthenticated
                    print(error.localizedDescription)
                    return false
                }
            }
            
        case .reauth:
            Task {
                if let user = Auth.auth().currentUser {
                    do {
                        try await user.reauthenticate(with: credential)
                        return true
                    } catch {
                        print(error.localizedDescription)
                        return false
                    }
                }
            }
        }
    }
}

CodePudding user response:

I don't have all your types, so here is a simple example of a continuation which at least compiles.

The class must inherit from NSObject and adopt ASAuthorizationControllerDelegate.

The continuation is set in the same scope where the request is executed.

The most important rule is: The continuation must be resumed exactly once

import AuthenticationServices

class Authorization: NSObject, ASAuthorizationControllerDelegate {
    
    private var continuation : CheckedContinuation<ASAuthorization,Error>?
    
    func signInWithApple() async throws -> ASAuthorization {
        return try await withCheckedThrowingContinuation { continuation in
    
            self.continuation = continuation
            let appleIDProvider = ASAuthorizationAppleIDProvider()
            let request = appleIDProvider.createRequest()
            request.requestedScopes = [.fullName, .email]
            let authorizationController = ASAuthorizationController(authorizationRequests: [request])
            authorizationController.delegate = self
            authorizationController.performRequests()
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        continuation?.resume(returning: authorization)
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        continuation?.resume(throwing: error)
    }
}
  • Related