RxFlow in Swift

#Introduction
**RxFlow** is a navigation framework for iOS applications based on a Flow Coordinator pattern. It is also important to keep in mind that RxFlow uses protocol oriented programming so that it doesn’t freeze your code in an inheritance hierarchy. **RxFlow** removes the navigation code from the View Controllers and it promotes **Dependency Injection**.
**RxFlow** is mainly about handling navigation state changes in a reactive way. In order to be reused in multiple contexts, these states must be unaware of the current navigation Flow the user is in. Therefore, instead of meaning “I want to go to this screen”, a state will rather mean “Someone or something has done this action” and RxFlow will pick the right screen according to the current navigation Flow. With RxFlow, this navigation states are called Steps.

![RxFlow_logo.png](https://qiita-image-store.s3.amazonaws.com/0/279562/73422d1c-3bcb-4d56-e051-8cea25057b81.png)


#Terminology
**Flow**: each Flow defines a navigation area within your application.
**Step**: each Step is a navigation state in your application. Combinaisons of Flows and Steps describe all the possible navigation actions.
**Stepper**: it can be anything that can emit Steps. Steppers will be responsible for triggering every navigation actions within the Flows
**Presentable**: it is an abstraction of something that can be presented, basically UIViewController and Flow are Presentable
NextFlowItem: it tells the Coordinator what will be the next thing that will produce new Steps in its Reactive mechanism
**Coordinator**: the job of the Coordinator is to mix combinaisons of Flows and Steps in a consistent way.
#Example 

```swift
enum AppStep: Step {
    case intro
    case details
}
```
Flow has to implement:
- “navigate(to:)” function that makes the navigation actions happen according the Flow and the Step
- “root” UIViewController on which will be based the navigation in this Flow

```swift
class AppFlow: Flow {
    // MARK: - Properties
    var root: Presentable {
        return self.rootViewController
    }
    private let viewModel: AppViewModel
    private lazy var rootViewController: UINavigationController = {
        let vc = UINavigationController()
        vc.setNavigationBarHidden(false, animated: true)
        return vc
    }()

    // MARK: - Init
    init(stepper viewModel: AppViewModel) {
        self.viewModel = viewModel
    }

    // MARK: - Navigation switch
    func navigate(to step: Step) -> NextFlowItems {
        guard let step = step as? AppStep else { return NextFlowItems.none }
        switch step {
        case .intro:
            return navigateToIntro()
        case .details:
            return navigateToDetails()

        }
    }
}
```

When it navigates to the new screen 

```swift
// MARK: - Navigate to Intro
extension AppFlow {
    private func navigateToIntro() -> NextFlowItems {
        let viewControllerIntro: ViewController = ViewController()
        viewControllerIntro.setViewModel(viewModel: self.viewModel)
        let nexFlowItem = NextFlowItem(nextPresentable: viewControllerIntro, nextStepper: viewModel)
        return NextFlowItems.one(flowItem: nexFlowItem)
    }
}

// MARK: - Navigate to Details
extension AppFlow {
    private func navigateToDetails() -> NextFlowItems {
        let viewControllerDetail: ViewControllerDetail = ViewControllerDetail()
        viewControllerDetail.setViewModel(viewModel: self.viewModel)
        let nextFlowItem = NextFlowItem(nextPresentable: viewControllerDetail, nextStepper: viewModel)
    }
}

```

**Stepper** can be anything: a custom UIViewController, a ViewModel, a Presenter… Once it is registered in the Coordinator, a Stepper can emits Steps via its “step” property (which is a RxSwift subject). The Coordinator will listen for these Steps and call the Flow’s “navigate(to:)” function.
*For Example*:

```swift
class AppViewModel: Stepper {
    init() {
        self.step.accept(AppStep.intro)
    }

    public func toDetails() {
        self.step.accept(AppStep.details)
    }

    public func toIntro() {
        self.step.accept(AppStep.intro)
    }

    public func toSetupFlow() {
        self.step.accept(AppStep.setupFlow)
    }

    public func toFinished() {
```

toDetails function is called when user click a button to a detail screen. This function emits a new value in the “self.step” Rx stream.

**To Sum up process:**
- the *navigate(to:)* function is called with a Step as a parameter
- according to this *Step*, some navigation code is called (side effects)
- also according to this Step, NextFlowItems are produced. Therefore, Presentables and Steppers are registered into the Coordinator
- *Steppers* emit new Steps and here we go again

**Sample Code**
You can try to understand the RxFlow more with the sample code [here](https://github.com/SreyPichh/RxFlow-Test.git) in GitHub