Update README.md
RxSwift port of ReactiveAutomaton (State Machine).
TerminologyWhenever the word “signal” or “(signal) producer” appears (derived from ReactiveCocoa), they mean “hot-observable” and “cold-observable”.
Whenever the word “signal” or “(signal) producer” appears (derived from ReactiveCocoa), they mean “hot-observable” and “cold-observable”.
(Demo app is bundled in the project)
To make a state transition diagram like above with additional effects, follow these steps:
// 1. Define `State`s and `Input`s. enum State { case loggedOut, loggingIn, loggedIn, loggingOut } enum Input { case login, loginOK, logout, logoutOK case forceLogout } // Additional effects (`Observable`s) while state-transitioning. // (NOTE: Use `Observable.empty()` for no effect) let loginOKProducer = /* show UI, setup DB, request APIs, ..., and send `Input.loginOK` */ let logoutOKProducer = /* show UI, clear cache, cancel APIs, ..., and send `Input.logoutOK` */ let forcelogoutOKProducer = /* do something more special, ..., and send `Input.logoutOK` */ let canForceLogout: State -> Bool = [.loggingIn, .loggedIn].contains // 2. Setup state-transition mappings. let mappings: [Automaton<State, Input>.EffectMapping] = [ /* Input | fromState => toState | Effect */ /* ----------------------------------------------------------------*/ .login | .loggedOut => .loggingIn | loginOKProducer, .loginOK | .loggingIn => .loggedIn | .empty(), .logout | .loggedIn => .loggingOut | logoutOKProducer, .logoutOK | .loggingOut => .loggedOut | .empty(), .forceLogout | canForceLogout => .loggingOut | forceLogoutOKProducer ] // 3. Prepare input pipe for sending `Input` to `Automaton`. let (inputSignal, inputObserver) = Observable<Input>.pipe() // 4. Setup `Automaton`. let automaton = Automaton( state: .loggedOut, input: inputSignal, mapping: reduce(mappings), // combine mappings using `reduce` helper strategy: .latest // NOTE: `.latest` cancels previous running effect ) // Observe state-transition replies (`.success` or `.failure`). automaton.replies.subscribe(next: { reply in print("received reply = \(reply)") }) // Observe current state changes. automaton.state.asObservable().subscribe(next: { state in print("current state = \(state)") })
And let’s test!
let send = inputObserver.onNext expect(automaton.state.value) == .loggedIn // already logged in send(Input.logout) expect(automaton.state.value) == .loggingOut // logging out... // `logoutOKProducer` will automatically send `Input.logoutOK` later // and transit to `State.loggedOut`. expect(automaton.state.value) == .loggedOut // already logged out send(Input.login) expect(automaton.state.value) == .loggingIn // logging in... // `loginOKProducer` will automatically send `Input.loginOK` later // and transit to `State.loggedIn`. // 👨🏽 < But wait, there's more! // Let's send `Input.forceLogout` immediately after `State.loggingIn`. send(Input.forceLogout) // 💥💣💥 expect(automaton.state.value) == .loggingOut // logging out... // `forcelogoutOKProducer` will automatically send `Input.logoutOK` later // and transit to `State.loggedOut`.
MIT
©Copyright 2023 CCF 开源发展委员会 Powered by Trustie& IntelliDE 京ICP备13000930号
NOTE: This repository has been discontinued in favor of Actomaton.
RxAutomaton
RxSwift port of ReactiveAutomaton (State Machine).
Example
(Demo app is bundled in the project)
To make a state transition diagram like above with additional effects, follow these steps:
And let’s test!
License
MIT