Skip to content

Instantly share code, notes, and snippets.

@yingmu52
Last active August 19, 2017 03:03
Show Gist options
  • Save yingmu52/f109837cdb2205afc85bd84ad403f5f3 to your computer and use it in GitHub Desktop.
Save yingmu52/f109837cdb2205afc85bd84ad403f5f3 to your computer and use it in GitHub Desktop.
MVVM Login Form Demo
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