You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Here we have three **Flows**: **Application**, **Onboarding** and **Settings** which describe the three main navigation sections of the application.
69
-
- We also have three **Steps**: **Dashboard** (the default navigation state triggered at the application bootstrap), **Set the server** and **Login**.
70
-
71
-
Each one of these **Steps** will be triggered either because of user actions or because of backend state changes.
72
-
The crossing between a **Flow** and a **Step** represented by a colored chip will be a specific navigation action (such as a UIViewController popup).
73
-
It will be up to the **Coordinator** engine to trigger the "navigate(to:)" function on the appropriate **Flow**.
74
-
75
-
## Flow, Step and Flowable
76
-
Combinaisons of **Flows** and **Steps** describe all the possible navigation actions within your application.
77
-
Each **Flow** defines a clear navigation area (that makes your application divided in well defined parts) in which every **Step** will lead to a specific navigation action (push a VC on a stack, pop up a VC, ...).
56
+
# The key principles
78
57
79
-
In the end, the **Flow.navigate(to:)** function has to return an array of **Flowable**.
58
+
The **Coordinator** pattern is a great way to organize the navigation within your application. It allows to:
59
+
- remove the navigation code from UIViewControllers
60
+
- reuse UIViewControllers in different navigation contexts
61
+
- ease the use of dependency injection
80
62
81
-
A **Flowable** tells the **Coordinator** engine "The next thing that can produce new **Steps** in your Reactive mechanism are":
82
-
- this particular next **Presentable**
83
-
- this particular next **Stepper**
63
+
To learn more about it, I suggest you take a look at this article: ([Coordinator Redux](http://khanlou.com/2015/10/coordinators-redux/)).
84
64
85
-
In some cases, the **navigate(to:)** function can return an empty array of **Flowable** because we know there won't be any further navigation after the one we are doing.
65
+
To me, the Coordinator pattern has some drawbacks:
66
+
- you have to write the coordination mechanism each time you bootstrap an application
67
+
- there can be a lot of boilerplate code because of the delegation pattern that allows to communicate with Coordinators
86
68
87
-
For the record, the Demo application shows pretty much every possible cases.
69
+
RxFlow is a reactive implementation of the Coordinator pattern. It has all the great features of this architecture, but introduces some improvements:
70
+
- makes the navigation more declarative
71
+
- provides a built-in Coordinator that handles the navigation flows you've declared
72
+
- uses reactive programming to address the communication with Coordinators issue
88
73
89
-
## Presentable
90
-
Presentable is an abstraction of something that can be presented.
91
-
Because a **Step** cannot be emitted unless its associated **Presentable** is displayed,
92
-
**Presentable** offers Reactive observables that the **Coordinator** will subscribe to (so it will be aware of the presentation state of the **Presentable**).
93
-
Therefore there is no risk of firing a new **Step** while its **Presentable** is not yet fully displayed.
94
-
95
-
## Stepper
96
-
A **Stepper** can be anything: a custom UIViewController, a ViewModel, a Presenter…
97
-
Once it is registered in the **Coordinator** engine, a **Stepper** can emits new **Steps** via its “steps” property (which is a Rx BehavorSubject).
98
-
The **Coordinator** will listen for these **Steps** and call the **Flow**’s “navigate(to:)” function.
99
-
100
-
A **Step** can even embed inner values (such as Ids, URLs, ...) that will be propagated to screens presented by the **Flows**.
101
-
102
-
## Coordinator
103
-
A **Coordinator** is a just a tool for the developper. Once he has defined the suitable combinations of **Flows** and **Steps** representing the navigation possibilities, the job of the **Coordinator** is to mix these combinaisons into a consistent navigation, according to navigation **Steps** changes induced by **Steppers**.
104
-
105
-
It is up to the developper to:
106
-
- define the **Flows** that represent in the best possible way its application sections (such as Dashboard, Onboarding, Settings, ...) in which significant navigation actions are needed
107
-
- provide the **Steppers** that will trigger the **Coordinator** process.
74
+
There are 6 terms you have to be familiar with to understand **RxFlow**:
75
+
-**Flow**: each **Flow** defines a navigation area within your application. This is the place where you declare the navigation actions (such as presenting a UIViewController or another Flow)
76
+
-**Step**: each **Step** is a navigation state in your application. Combinaisons of **Flows** and **Steps** describe all the possible navigation actions. A **Step** can even embed inner values (such as Ids, URLs, ...) that will be propagated to screens declared in the **Flows**
77
+
-**Stepper**: it can be anything that can emit **Steps**. **Steppers** will be responsible for triggering every navigation actions within the **Flows**
78
+
-**Presentable**: it is an abstraction of something that can be presented (basically **UIViewController** and **Flow** are **Presentable**). **Presentables** offer Reactive observables that the **Coordinator** will subscribe to in order to handle **Flow Steps** in a UIKit compliant way
79
+
-**Flowable**: it is a simple data structure that combines a **Presentable** and a **stepper**. It tells the **Coordinator** what will be the next thing that will produce new **Steps** in your Reactive mechanism
80
+
-**Coordinator**: once the developer has defined the suitable combinations of **Flows** and **Steps** representing the navigation possibilities, the job of the **Coordinator** is to mix these combinaisons in a consistent way.
108
81
109
82
# How to use RxFlow
110
83
111
84
## Code samples
112
85
113
86
### How to declare **Steps**
114
87
115
-
As **Steps** are seen like some states spread across the application, it seems pretty obvious to use an enum to declare them
88
+
As **Steps** are seen like some navigation states spread across the application, it seems pretty obvious to use an enum to declare them
116
89
117
90
```swift
118
91
enumDemoStep: Step {
@@ -132,7 +105,11 @@ enum DemoStep: Step {
132
105
133
106
### How to declare a **Flow**
134
107
135
-
The following **Flow** is used as a Navigation stack.
108
+
The following **Flow** is used as a Navigation stack. All you have to do is:
109
+
- declare a root UIViewController on which your navigation will be based
110
+
- implement the **navigate(to:)** function to transform a **Step** into a navigation action
111
+
112
+
The **navigate(to:)** function returns an array of **Flowable**. This is how the next navigation actions will be produced (the **Stepper** defined in a **Flowable** will emit the next **Steps**)
In theory a **Stepper**, as it is a protocol, can be anything (a UIViewController for instance) by I suggest to isolate that behavior in a ViewModel or so.
198
-
For simple cases (for instance when we only need to bootstrap a **Flow** with a first **Step** and don't want to code a basic **Stepper** for that), RxFlow provides a OneStepper class.
174
+
For simple cases (for instance when we only need to bootstrap a **Flow** with a first **Step** and don't want to code a basic **Stepper** for that), RxFlow provides a **OneStepper** class.
199
175
200
176
```swift
201
177
classWatchedViewModel: Stepper {
@@ -209,8 +185,10 @@ class WatchedViewModel: Stepper {
209
185
})
210
186
}
211
187
188
+
// when a movie is picked, a new Step is emitted.
189
+
// That will trigger a navigation action within the WatchedFlow
As a bonus, the **Coordinator** offers a Rx extension that allows you to track the navigation actions (Coordinator.rx.willKnit and Coordinator.rx.didKnit).
237
+
As a bonus, **Coordinator** offers a Rx extension that allows you to track the navigation actions (Coordinator.rx.willNavigate and Coordinator.rx.didNavigate).
255
238
256
239
## Demo Application
257
240
A demo application is provided to illustrate the core mechanisms. Pretty much every kind of navigation is addressed. The app consists of:
@@ -271,3 +254,4 @@ RxFlow relies on:
271
254
- SwiftLint for static code analysis ([Github SwiftLint](https://github.com/realm/SwiftLint))
272
255
- RxSwift to expose Wefts into Observables the Loom can react to ([Github RxSwift](https://github.com/ReactiveX/RxSwift))
273
256
- Reusable in the Demo App to ease the storyboard cutting into atomic ViewControllers ([Github Reusable](https://github.com/AliSoftware/Reusable))
0 commit comments