Last active
August 19, 2017 03:03
-
-
Save yingmu52/f109837cdb2205afc85bd84ad403f5f3 to your computer and use it in GitHub Desktop.
MVVM Login Form Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import ReactiveSwift | |
import Result | |
import ReactiveCocoa | |
class TestVC: UIViewController { | |
@IBOutlet weak var emailTextField : UITextField! | |
@IBOutlet weak var nameTextField : UITextField! | |
@IBOutlet weak var passTextField : UITextField! | |
@IBOutlet weak var submitButton : UIButton! | |
let vm = MyViewModel() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.navigationItem.reactive.title <~ self.vm.output.alertMessage | |
self.submitButton.reactive.isEnabled <~ self.vm.output.submiteButtonEnabled | |
self.vm.input.emailChangedProperty <~ self.emailTextField.reactive.continuousTextValues | |
self.vm.input.passChangedProperty <~ self.passTextField.reactive.continuousTextValues | |
self.vm.input.nameChangedProperty <~ self.nameTextField.reactive.continuousTextValues | |
self.vm.input.submitButtonPressedProperty <~ self.submitButton.reactive.controlEvents(.touchUpInside).map {_ in} | |
} | |
} | |
// ##################### View Model | |
protocol MyViewModelInput { | |
var nameChangedProperty : MutableProperty<String?> {get} | |
var emailChangedProperty : MutableProperty<String?> {get} | |
var passChangedProperty : MutableProperty<String?> {get} | |
var submitButtonPressedProperty: MutableProperty<Void> {get} | |
} | |
protocol MyViewModelOutput { | |
var alertMessage: Signal<String, NoError> { get } | |
var submiteButtonEnabled: Signal<Bool, NoError> { get } | |
} | |
protocol MyViewModelType { | |
var input: MyViewModelInput { get } | |
var output: MyViewModelOutput { get } | |
} | |
class MyViewModel: MyViewModelOutput, MyViewModelInput, MyViewModelType { | |
var input: MyViewModelInput { return self } | |
var output: MyViewModelOutput { return self } | |
let nameChangedProperty = MutableProperty<String?>(nil) | |
var emailChangedProperty = MutableProperty<String?>(nil) | |
let passChangedProperty = MutableProperty<String?>(nil) | |
let submitButtonPressedProperty = MutableProperty() | |
var alertMessage : Signal<String, NoError> = .empty | |
var submiteButtonEnabled: Signal<Bool, NoError> = .empty | |
init() { | |
let formData = Signal | |
.combineLatest(emailChangedProperty.signal, nameChangedProperty.signal, passChangedProperty.signal) | |
// takes the latest formData only when submit button is pressed | |
let successMsg = formData | |
.sample(on: submitButtonPressedProperty.signal) | |
.filter(Helper.isValid(email:name:password:)) | |
.map { _ in "Successful" } | |
let inValidFormData = formData | |
.sample(on: self.submitButtonPressedProperty.signal) | |
.filter(Helper.isInValid(email:name:password:)) | |
let unsuccessMsg = inValidFormData | |
.take(first: 2) | |
.map { _ in "Unsuccessful" } | |
let toomany = inValidFormData | |
.skip(first: 2) | |
.map { _ in "Too many attempts" } | |
self.alertMessage = Signal.merge(successMsg, unsuccessMsg, toomany) | |
self.submiteButtonEnabled = Signal | |
.merge( formData.map(Helper.isValid(email:name:password:)), | |
toomany.map{ _ in false }) | |
.take(until: toomany.map({ _ in})) | |
} | |
} | |
class Helper { | |
public static func isValidEmail(_ email: String) -> Bool { | |
let regex = try? NSRegularExpression( | |
pattern: "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}\\@" + | |
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}(\\." + | |
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+", | |
options: [] | |
) | |
let range = NSRange.init(location: 0, length: email.characters.count) | |
return regex?.firstMatch(in: email, options: [], range: range) != nil | |
} | |
public static func isValid(email: String?, name: String?, password: String?) -> Bool { | |
guard let email = email, let name = name, let password = password | |
else { return false } | |
return isValidEmail(email) | |
&& name.characters.count > 0 | |
&& password.characters.count > 0 | |
} | |
public static func isInValid(email: String?, name: String?, password: String?) -> Bool { | |
return !isValid(email: email, name: name, password: password) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment