Connection
public class Connection<State, Props, Actions> : StoreSubscriber where State : StateType
A ReRxSwift Connection that manages the mapping between ReSwift application state and ReSwift actions on the one hand, and view controller props and actions on the other hand.
In order to use this, you have to make your view controller conform to
Connectable
and add a Connection
instance. In your view controller
you need to call connect()
and disconnect()
at the right time.
Examples
The folder Example
contains example of how to use this.
Usage
Create an extension to your view controller to make it
Connectable
, defining theProps
andActions
that your view controller needs:extension MyViewController: Connectable { struct Props { let text: String } struct Actions { let updatedText: (String) -> Void } }
Define how your state is mapped to the above
Props
type:private let mapStateToProps = { (appState: AppState) in return MyViewController.Props( text: appState.content ) }
Define the actions that are dispatched:
private let mapDispatchToActions = { (dispatch: @escaping DispatchFunction) in return MyViewController.Actions( updatedText: { newText in dispatch(SetContent(newContent: newText)) } ) }
Define the connection and hook it up:
class MyViewController: UIViewController { @IBOutlet weak var textField: UITextField! let connection = Connection( store: store, mapStateToProps: mapStateToProps, mapDispatchToActions: mapDispatchToActions ) override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) connection.connect() } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) connection.disconnect() } }
Bind the text field’s text, using a Swift 4 key path to refer to the
text
property ofProps
:override func viewDidLoad() { super.viewDidLoad() connection.bind(\Props.text, to: textField.rx.text) }
Call the action:
@IBAction func editingChanged(_ sender: UITextField) { actions.updatedText(sender.text ?? "") }
-
The RxSwift
BehaviorRelay
that holds your view controller props. Normally you don’t use this this directly, you use it throughConnectable.props
instead. This variable is public so that you can use it for unit testing. In cases where you don’t want to use thebind(_:to:)
methods in this class and want to create your own RxSwift observing code, you do need to use this variable directly.Declaration
Swift
public let props: BehaviorRelay<Props>
-
This holds you view controller’s actions. Don’t use this directly, use
Connectable.actions
instead. This variable is public so that you can use it for unit testing.Declaration
Swift
public var actions: Actions!
-
The ReSwift store used by this connection object. Normally you pass your global app store as a parameter to the constructor. This variable is public so that you can inject a different store during unit testing. It is not intended to be used directly from production code.
Declaration
Swift
public var store: Store<State> { get set }
-
RxSwift memory management.
Declaration
Swift
public let disposeBag: DisposeBag
-
Constructs a new
Connection
object. For examples see the class documentation above, or the code examples inSimpleTextFieldViewController
andSteppingUpViewController
.Declaration
Swift
public init(store: Store<State>, mapStateToProps: @escaping (State) -> (Props), mapDispatchToActions: @escaping (@escaping DispatchFunction) -> (Actions) )
Parameters
store
Your application’s global store.
mapStateToProps
A mapping function that takes the global application state, and maps it into a view controller specific structure
Connectable.props
. Whenever a new state comes in from your ReSwift store, the connection calls this function to map it to theConnectable.props
needed by your view controller.mapDispatchToActions
A mapping function that specifies which ReSwift action needs to be dispatched when your view controller calls its
Connectable.actions
. -
“Activates” the connection in the sense that it subscribes to the store so that store updates are received and can be processed. Failing to call this method will mean that your view controller does not get new
Connectable.props
when the global state changes. Call this method from your view controller’sviewWillAppear()
orviewDidAppear()
.Declaration
Swift
public func connect()
-
“Deactivates” the connection: unsubscribes from the store so that state updates are no longer processed for your view controller. Call this method from your view controller’s
viewWillDisappear()
orviewDidDisappear()
.Declaration
Swift
public func disconnect()
-
ReSwift’s callback method. Don’t call this yourself.
Declaration
Swift
public func newState(state: State)
-
Undocumented
Declaration
Swift
public func propsEntry<T>(at keyPath: KeyPath<Props, T>, isEqual: @escaping (T,T) -> Bool) -> Observable<T>
-
Bind a RxSwift observer to one of your
Connectable.props
entries. Convenience method forbind(keyPath, to: observer, mapping: nil)
.Declaration
Swift
public func bind<T: Equatable, O>(_ keyPath: KeyPath<Props, T>, to observer: O) where O: ObserverType, O.Element == T?
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to bind.observer
The RxSwift observer that you want to bind to.
-
Bind a RxSwift observer to one of your
Connectable.props
entries.All
bind()
functions are variants of the following basic implementation:self.props .asObservable() .distinctUntilChanged { $0[keyPath: keyPath] == $1[keyPath: keyPath] } .map { $0[keyPath: keyPath] } .map(mapping) // if not nil .bind(to: binder) .disposed(by: disposeBag)
Declaration
Swift
public func bind<T: Equatable, O, M>(_ keyPath: KeyPath<Props, T>, to observer: O, mapping: ((T)->M)? = nil) where O: ObserverType, O.Element == M?
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to bind.observer
The RxSwift observer that you want to bind to.
mapping
An optional function that takes the entry in your
Connectable.props
and converts it to the thing needed by the observable. This is useful if yourConnectable.props
entry is a different type that needs to be converted before it can be put into the observer, for example converting aFloat
into aString
so that it can be put in a text field’stext
.
-
Subscribe to one of your
Connectable.props
entries, having a closure called whenever it changes. Variant for non-optional entries.Declaration
Swift
public func subscribe<T: Equatable>(_ keyPath: KeyPath<Props, T>, onNext: @escaping (T)->())
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to subscribe to.onNext
The closure that is called whenever the entry at the given key path changes. The new value is passed into the closure as a parameter.
-
Bind a RxSwift observer to one of your
Connectable.props
entries. Convenience method forbind(keyPath, to: observer, mapping: nil)
.Declaration
Swift
public func bind<T: Equatable, O>(_ keyPath: KeyPath<Props, T>, to observer: O) where O: ObserverType, O.Element == T
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to bind.observer
The RxSwift observer that you want to bind to.
-
Bind a RxSwift observer to one of your
Connectable.props
entries.All
bind()
functions are variants of the following basic implementation:self.props .asObservable() .distinctUntilChanged { $0[keyPath: keyPath] == $1[keyPath: keyPath] } .map { $0[keyPath: keyPath] } .map(mapping) // if not nil .bind(to: binder) .disposed(by: disposeBag)
Declaration
Swift
public func bind<T: Equatable, O, M>(_ keyPath: KeyPath<Props, T>, to observer: O, mapping: ((T)->M)? = nil) where O: ObserverType, O.Element == M
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to bind.observer
The RxSwift observer that you want to bind to.
mapping
An optional function that takes the entry in your
Connectable.props
and converts it to the thing needed by the observable. This is useful if yourConnectable.props
entry is a different type that needs to be converted before it can be put into the observer, for example converting aFloat
into aString
so that it can be put in a text field’stext
.
-
Subscribe to one of your
Connectable.props
entries, having a closure called whenever it changes. Variant for non-optional entries.Declaration
Swift
public func subscribe<T: Equatable>(_ keyPath: KeyPath<Props, [T]>, onNext: @escaping ([T])->())
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to subscribe to.onNext
The closure that is called whenever the entry at the given key path changes. The new value is passed into the closure as a parameter.
-
Bind a RxSwift observer to one of your
Connectable.props
entries.Declaration
Swift
public func bind<S: Sequence,M>(_ keyPath: KeyPath<Props, S>, to binder: (Observable<M>) -> Disposable, mapping: ((S)->M)? = nil) where S.Element: Equatable
Parameters
keyPath
Swift 4
KeyPath
that points to the entry in your view controllersConnectable.props
that you want to bind.binder
The RxSwift binder function such as used by
UICollectionView.rx.items
andUITableView.rx.items
.