Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save stud214/43cb1e8a0bf4fc97d7b20ae4ded82b5e to your computer and use it in GitHub Desktop.
Save stud214/43cb1e8a0bf4fc97d7b20ae4ded82b5e to your computer and use it in GitHub Desktop.
 Sign in with Apple + Rx
import AuthenticationServices
import RxCocoa
import RxSwift
import UIKit
@available(iOS 13.0, *)
extension ASAuthorizationController: HasDelegate {
public typealias Delegate = ASAuthorizationControllerDelegate
}
@available(iOS 13.0, *)
class ASAuthorizationControllerProxy: DelegateProxy<ASAuthorizationController, ASAuthorizationControllerDelegate>, DelegateProxyType, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
var presentationWindow: UIWindow = UIWindow()
public init(controller: ASAuthorizationController) {
super.init(parentObject: controller, delegateProxy: ASAuthorizationControllerProxy.self)
}
// MARK: - DelegateProxyType
public static func registerKnownImplementations() {
register { ASAuthorizationControllerProxy(controller: $0) }
}
// MARK: - Proxy Subject
internal lazy var didComplete = PublishSubject<ASAuthorization>()
// MARK: - ASAuthorizationControllerDelegate
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
didComplete.onNext(authorization)
didComplete.onCompleted()
}
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
didComplete.onCompleted()
}
// MARK: - ASAuthorizationControllerPresentationContextProviding
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return presentationWindow
}
// MARK: - Completed
deinit {
self.didComplete.onCompleted()
}
}
import AuthenticationServices
import RxCocoa
import RxSwift
import UIKit
@available(iOS 13.0, *)
extension Reactive where Base: ASAuthorizationAppleIDProvider {
public func login(scope: [ASAuthorization.Scope]? = nil, on window: UIWindow) -> Observable<ASAuthorization> {
let request = base.createRequest()
request.requestedScopes = scope
let controller = ASAuthorizationController(authorizationRequests: [request])
let proxy = ASAuthorizationControllerProxy.proxy(for: controller)
proxy.presentationWindow = window
controller.presentationContextProvider = proxy
controller.performRequests()
return proxy.didComplete
}
}
@available(iOS 13.0, *)
extension Reactive where Base: ASAuthorizationAppleIDButton {
public func loginOnTap(scope: [ASAuthorization.Scope]? = nil) -> Observable<ASAuthorization> {
let window = base.window!
return controlEvent(.touchUpInside)
.flatMap {
ASAuthorizationAppleIDProvider().rx.login(scope: scope, on: window)
}
}
public func login(scope: [ASAuthorization.Scope]? = nil) -> Observable<ASAuthorization> {
return ASAuthorizationAppleIDProvider().rx.login(scope: scope, on: base.window!)
}
}
import AuthenticationServices
let appleLoginButton = ASAuthorizationAppleIDButton()
//...
appleLoginButton.rx
.loginOnTap(scope: [.fullName, .email])
.subscribe(onNext: { result in
guard let auth = result.credential as? ASAuthorizationAppleIDCredential else { return }
print(auth.user)
print(auth.email)
print(auth.fullName?.givenName)
print(auth.fullName?.familyName)
})
.disposed(by: disposeBag)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment