The code is very similar to the tutorials and documentation. The difference is I am using MVVM+RxSwift. Here it is:
Code Block final class SignInViewModel { |
struct Input { |
let emailText: Driver<String> |
let passwordText: Driver<String> |
let signInTapped: Signal<Void> |
let appleSignInTapped: Signal<Void> |
} |
|
let openDashboardScreen: Signal<SignInViewParam> |
|
init(handleSignIn: @escaping (String, String) -> Observable<SignInViewParam>, |
handleAppleSignIn: @escaping (String) -> Observable<SignInViewParam>, |
input: Input) { |
let signInEvent = input.signInTapped |
.asObservable() |
.withLatestFrom(Observable.combineLatest(input.emailText.asObservable(), |
input.passwordText.asObservable())) |
.flatMapLatest { (arg) -> Observable<SignInViewParam> in |
let (email, password) = arg |
return handleSignIn(email, password) |
} |
|
if #available(iOS 13, *) { |
let appleSignInEvent = input.appleSignInTapped |
.compactMap { [weak self] in return self?.createAuthController() } |
.flatMapLatest { (authController: ASAuthorizationController) -> Observable<SignInViewParam> in |
return authController.rx |
.didCompleteWithAuthorization /* The delegate control event using RxCocoa's DelegateProxy */ |
.compactMap { authorization in |
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential, |
let authCodeData = credential.authorizationCode, |
let authCode = String(data: authCodeData, encoding: .utf8) |
else { return nil } |
|
return authCode |
} |
.flatMapLatest { (authCode) -> Observable<SignInViewParam> in |
return handleAppleSignIn(authCode) /* Send auth code to server and will return SignInViewParam on success */ |
} |
} |
|
openDashboardScreen = Observable.merge(signInEvent, appleSignInEvent) |
.asSignal(onErrorSignalWith: .never()) |
} else { |
openDashboardScreen = signInEvent.asSignal(onErrorSignalWith: .never()) |
} |
} |
|
@available(iOS 13.0, *) |
private func createAuthController() -> ASAuthorizationController { |
let appleIdProvider = ASAuthorizationAppleIDProvider() |
let request = appleIdProvider.createRequest() |
request.requestedScopes = [.email, .fullName] |
|
let authController = ASAuthorizationController(authorizationRequests: [request]) |
authController.performRequests() |
return authController |
} |
} |
I tried using imperative instead of reactive like the tutorials, and it still stuck on the Apple ID password screen.