Skip to content

RxViewBinder is a one-way architecture framework using Reactive.

License

Notifications You must be signed in to change notification settings

magi82/RxViewBinder

Repository files navigation

RxViewBinder

Swift Platform Version Carthage compatible License

RxViewBinder is a simple one-way architecture.
Simple and easy to implement. ☀️

It is implemented as a reactive extension.

Flow

Usage (ViewBindable)

  • Create a ViewBinder class that implements ViewBindable.
    Command, Action, State must be implemented.
    Command is enum type.
    Action, State is structure type.

important!!
You need to bind the action and state in the constructor of the state structure.

final class SampleViewBinder: ViewBindable {
  
  enum Command {
    case fetch
  }
  
  struct Action {
    let value: PublishRelay<String> = PublishRelay()
  }
  
  struct State {
    let value: Driver<String>
    
    init(action: Action) {
      // Action and state binding
      value = action.value.asDriver(onErrorJustReturn: "")
    }
  }
  
  let action = Action()
  lazy var state = State(action: self.action)
}
  • implements a binding method that accepts a command stream and sends the stream to action.
    When changing the state of ui, only action is used.
    state is used only when the view receives the state of ui.
  func binding(command: Command) {
    switch command {
    case .fetch:
      Observable<String>.just("test")
        .bind(to: action.value)
        .disposed(by: self.disposeBag)
    }
  }
  • Or you can simply send the stream without creating an observer.
  func binding(command: Command) {
    switch command {
    case .fetch:
      action.value.accept("test")
    }
  }

Usage (BindView)

  • Implement the BindView protocol on the view controller.
    It injects the view binder at initialization.
final class ViewController: UIViewController, BindView {

  typealias ViewBinder = SampleViewBinder
  
  init(viewBinder: ViewBinder) {
    defer { self.viewBinder = viewBinder }
    
    super.init(nibName: nil, bundle: nil)
  }
}
  • If you are using a storyboard, you have to inject it in a different way.
  let vc = ViewController()
  vc.viewBinder = SampleViewBinder()

or

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    
    self.viewBinder = ViewBinder()
  }
  • Implements the command and state methods.
  func command(viewBinder: ViewBinder) {
    self.rx.methodInvoked(#selector(UIViewController.viewDidLoad))
      .map { _ in ViewBinder.Command.fetch }
      .bind(to: viewBinder.command)
      .disposed(by: self.disposeBag)
  }
  
  func state(viewBinder: ViewBinder) {
    viewBinder.state
      .value
      .drive(onNext: { print($0) })
      .disposed(by: self.disposeBag)
  }

Requirements

  • Swift 5.0+
  • iOS 9.0+

Installation

pod 'RxViewBinder', '~> 2.0.0'
github "magi82/RxViewBinder" ~> 2.0.0

Author

magi82, devmagi82@gmail.com

License

RxViewBinder is available under the MIT license. See the LICENSE file for more info.