LoginProvider is a sample tool to add login with tiers service (as Facebook, Google, or Twitter), using RxSwift.
| CameraEngine
--------------------------|------------------------------------------------------------ :star2: | RxSwift implementation :star2: | Modulable, and easy to extend F | Facebook integration G | Google+ integration
#How to create a LoginProvider
Following to the protocol, you can create your own Provider.
protocol Provider {
var providerType: LoginProviderType {get}
var delegate: LoginProviderDelegate? {get set}
func login()
}
Example of a Provider login with Email :
class EmailProvider: Provider {
private var email: String
private var password: String
let providerType = LoginProviderType.Email
var delegate: LoginProviderDelegate?
init(email: String, password: String) {
self.email = email
self.password = password
}
func isValid() -> Bool {
//check the email here regex or everything you want.
//If you don't know what you want, please skip this method 😳.
//Avoid the boring stuff please.
return true
}
func login() {
if self.isValid() {
//You can make a call here in your API to fetch auth return
self.delegate?.loginProvider(self, didSucceed: APIAuth.Email(email: self.email, password: self.password))
}
else {
self.delegate?.loginProvider(self, didError: nil)
}
}
}
#RxSwift
To handle the login more easier, and more generic, RxSwft is used to handle the return of the Provider.
class ViewController: UIViewController {
@IBOutlet weak var buttonGoogleConnect: UIButton!
@IBOutlet weak var buttonFacebookConnect: UIButton!
private let disposeBag = DisposeBag()
private let loginProvider = LoginProvider()
private lazy var observerGoogle: Observable<Provider>! = {
self.buttonGoogleConnect.rx_tap.map {
return GoogleProvider(parentController: self)
}
}()
private lazy var observerFacebook: Observable<Provider>! = {
self.buttonFacebookConnect.rx_tap.map {
return FacebookProvider(parentController: self)
}
}()
override func viewDidLoad() {
super.viewDidLoad()
Observable.of(self.observerFacebook, self.observerGoogle)
.merge()
.flatMap { (provider: Provider) -> Observable<Bool> in
return self.loginViewModel.login(self.loginProvider, provider: provider)
}.subscribe { (event) -> Void in
switch event {
case .Completed: print("success")
case .Error(let error): print("get errro : \(error)")
default: break
}
}.addDisposableTo(self.disposeBag)
}
}
#AppDelegate
In some case you will need to route several URLS from the AppDelegate, for example with Facebook and Google. One way to do deal with that :
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
if url.scheme.rangeOfString("com.googleusercontent") != nil {
//Google here :
let options: [String: AnyObject] = [UIApplicationOpenURLOptionsSourceApplicationKey: sourceApplication!, UIApplicationOpenURLOptionsAnnotationKey: annotation]
return GIDSignIn.sharedInstance().handleURL(url,
sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as! String,
annotation: options[UIApplicationOpenURLOptionsAnnotationKey])
}
else {
//Facebook here :
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
}