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.