Home > database >  How to return to "View Parent" from ASWebAutheticationSession
How to return to "View Parent" from ASWebAutheticationSession

Time:10-05

How to return from the ASWebAutheticationSession completion handler back to the View?

Edit: Just for clearance this is not the original code in my project this is extremely shortened and is just for showcasing what I mean.

Here's an example of a code

struct SignInView: View {
    
    @EnvironmentObject var signedIn: UIState
    
    var body: some View {
        let AuthenticationSession = AuthSession()
        AuthenticationSession.webAuthSession.presentationContextProvider = AuthenticationSession
        AuthenticationSession.webAuthSession.prefersEphemeralWebBrowserSession = true
        AuthenticationSession.webAuthSession.start()
    }
}

class AuthSession: NSObject, ObservableObject, ASWebAuthenticationPresentationContextProviding {
    var webAuthSession = ASWebAuthenticationSession.init(
        url: AuthHandler.shared.signInURL()!,
        callbackURLScheme: "",
        completionHandler: { (callbackURL: URL?, error: Error?) in
            
            // check if any errors appeared
            
            // get code from authentication

            // Return to view to move on with code? (return code)
        })

    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {

        return ASPresentationAnchor()
    }

}

So what I'm trying to do is call the sign In process and then get back to the view with the code from the authentication to move on with it.

Could somebody tell me how this may be possible? Thanks.

CodePudding user response:

Not sure if I'm correctly understanding your question but it is normally done with publishers, commonly with the @Published wrapper, an example:

import SwiftUI
import Combine

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        VStack {
            Button {
                self.viewModel.signIn(user: "example", password: "example")
            }
            label: {
                Text("Sign in")
            }
            
            if self.viewModel.signedIn {
                Text("Successfully logged in")
            }
            else if let error = self.viewModel.signingError {
                Text("Error while logging in: \(error.localizedDescription)")
            }
        }
        .padding()
    }
}

class ViewModel: ObservableObject {
    @Published var signingStatus = SigningStatus.idle
    
    var signedIn: Bool {
        if case .success = self.signingStatus { return true }
        
        return false
    }
    
    var signingError: Error? {
        if case .failure(let error) = self.signingStatus { return error }
        
        return nil
    }
    
    func signIn(user: String, password: String) {
        self.dummyAsyncProcessWithCompletionHandler { [weak self] success in
            guard let self = self else { return }
            
            guard success else {
                self.updateSigning(.failure(CustomError(errorDescription: "Login failed")))
                return
            }
            
            self.updateSigning(.success)
        }
    }
    
    private func updateSigning(_ status: SigningStatus) {
        DispatchQueue.main.async {
            self.signingStatus = status
        }
    }
    
    private func dummyAsyncProcessWithCompletionHandler(completion: @escaping (Bool) -> ()) {
        Task {
            print("Signing in")

            try await Task.sleep(nanoseconds: 500_000_000)
            
            guard Int.random(in: 0..<9) % 2 == 0 else {
                print("Error")
                completion(false)
                return
            }
            
            print("Success")
            completion(true)
        }
    }
    
    enum SigningStatus {
        case idle
        case success
        case failure(Error)
    }
    
    struct CustomError: Error, LocalizedError {
        var errorDescription: String?
    }
}
  • Related