Skip to content

Instantly share code, notes, and snippets.

@JaviLorbada
Last active April 13, 2017 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JaviLorbada/daa84ea4f1f01659eb5516fdbb3275ea to your computer and use it in GitHub Desktop.
Save JaviLorbada/daa84ea4f1f01659eb5516fdbb3275ea to your computer and use it in GitHub Desktop.
RAC ViewModel Action after button pressed with textfield char count as button enabled condition
import Result
import ReactiveCocoa
import ReactiveSwift
import UIKit
import XCPlayground
struct ViewModel {
// do not expose the implementation detail
private let (codeSignal, codeSink) = Signal<String, NoError>.pipe()
// change mutable to read-only
// this will not let the changes outside of VM
// and only through the `setCode` method
let code: Property<String>
let openAction: Action<String, String, NoError>
init() {
code = Property(initial: "", then: codeSignal)
let validCodes = Property(capturing: code.map { $0.characters.count > 4})
openAction = Action<String, String, NoError>(enabledIf: validCodes, { code -> SignalProducer<String, NoError> in
return SignalProducer<String, NoError> { observer, _ in
print("Code \(code) will be sent.")
observer.send(value: code)
observer.sendCompleted()
}
})
}
public func setCode(_ code: String) {
codeSink.send(value: code)
}
}
// UI Declarations
let textField = UITextField(frame: CGRect(x: 0, y: 0, width: 360, height: 44))
textField.textColor = .white
textField.text = "P2525"
let button = UIButton(frame: CGRect(x: 0, y: 50, width: 360, height: 44))
button.setTitle("Open", for: .normal)
// Bindings
let viewModel = ViewModel()
// add the `setCode(_:)` function as
// the observer to code text field changes
textField.reactive.continuousTextValues
.skipNil()
.observeValues(viewModel.setCode)
// When button is pressed, trigger viewModel action with the property value
button.reactive.pressed = CocoaAction(viewModel.openAction, { _ in
return viewModel.code.value
})
// bind button's isEnabled to action's isEnabled and action's executing
button.reactive.isEnabled <~ Signal.merge(viewModel.openAction.isEnabled.signal, viewModel.openAction.isExecuting.signal)
// Let's assume the user types and then presses the button, for playground use.
textField.sendActions(for: .allEditingEvents)
button.sendActions(for: .touchUpInside)
@JaviLorbada
Copy link
Author

Revisions have been made thanks to @eimantas and @sharplet, slack archive for better reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment