Contents

magi82/rxviewbinder

RxViewBinder is a simple one-way architecture.<br>

Flow

<img src="https://github.com/magi82/RxViewBinder/blob/master/Resources/flow.png?raw=true">

Usage (ViewBindable)

  • Create a ViewBinder class that implements ViewBindable.

<br>Command, Action, State must be implemented. <br>Command is enum type. <br>Action, State is structure type.

important!! <br>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.

<br>When changing the state of ui, only action is used. <br>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.

<br>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.

Package Metadata

Repository: magi82/rxviewbinder

Default branch: master

README: README.md