Skip to content

Commit da6a0ba

Browse files
committed
Edit L08
1 parent f7bef02 commit da6a0ba

File tree

3 files changed

+172
-190
lines changed

3 files changed

+172
-190
lines changed

Lessons/08-Coordinators/README.md

Lines changed: 72 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,31 @@ By the end of this lesson, you should be able to...
1616

1717
1. Describe:
1818
- the **Coordinator** design pattern
19-
- the software construction problem(s) it is intended to solve
20-
- potential use cases for it (when to use it; when not to use it)
21-
- how to implement Coordinator in iOS
19+
- the problem it is intended to solve
2220
3. Assess:
23-
- the suitability of a given design pattern to solve a given problem
21+
- when to use it
2422
- the trade offs (pros/cons)
25-
4. Design and implement basic examples of **Coordinator** explored in this class
23+
4. Implement basic examples of **Coordinator** explored in this class
2624

2725
<!-- > -->
2826

29-
## Initial Exercise
27+
## Initial Exercise (5 min)
3028

31-
### As A Class
29+
As a class:
3230

3331
1. Review assignment from last class
34-
- students demo their solutions
32+
- students demo their solutions in pairs
3533

3634
<!-- > -->
3735

3836
### The Coordinator Pattern
3937

40-
The idea behind the Coordinator pattern is the creation of a separate entity &mdash; __*a Coordinator object*__ &mdash; which is responsible for the application’s *flow.*
38+
The idea behind the Coordinator pattern is the creation of a separate entity &mdash; __*a Coordinator object*__ &mdash; which is responsible for the application’s *navigation.*
4139

4240
*So what is a coordinator?*
4341

42+
<!-- v -->
43+
4444
>
4545
> A **coordinator** is an object that bosses one or more view controllers around.
4646
>
@@ -51,10 +51,11 @@ The idea behind the Coordinator pattern is the creation of a separate entity &md
5151
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Source:* [Coordinators Redux](http://khanlou.com/2015/10/coordinators-redux/) &mdash; Soroush Khanlou
5252

5353

54-
<!-- > -->
54+
<!-- v -->
5555

5656
Similar to how UIViewControllers manage UIViews, Coordinators can manage UIViewControllers taking all of the driving logic (navigation) out of view controllers and moving it up one level &mdash; to a __*Coordinator layer.*__
5757

58+
<!-- v -->
5859

5960
![example](assets/coordinator_diagram.png)
6061

@@ -70,22 +71,20 @@ https://medium.com/@saad.eloulladi/ios-coordinator-pattern-in-swift-39a15aa3b01b
7071
One of the standard ways to perform navigation on iOS is to use a `UINavigationController` onto which each view controller can either pop or push other view controllers.
7172

7273
```Swift
73-
if let vc = storyboard?.instantiateViewController(withIdentifier: "SomeVC") {
74-
navigationController?.pushViewController(vc, animated: true)
75-
}
74+
navigationController?.pushViewController(vc, animated: true)
7675
```
7776

78-
<!-- > -->
77+
<!-- v -->
7978

80-
When the view controllers themselves must decide the next view controller to push onto `self.navigationController`, the View controllers are too tightly coupled.
79+
When the view controllers themselves must decide the next view controller to push onto `self.navigationController`, the View controllers are **too tightly coupled**.
8180

82-
As an app grows, this approach becomes difficult to deal with: The codebase will be hard to change and maintain, and view controllers are almost impossible to reuse.
81+
<!-- v -->
8382

84-
<!-- > -->
83+
As an app grows, this approach becomes difficult to deal with:
8584

86-
What if...
87-
- you need to be able to navigate to the same view controller from multiple places?
88-
- you want to implement something like deep linking from outside your app?
85+
86+
- codebase is hard to change and maintain
87+
- view controllers are hard to reuse
8988

9089
<!--
9190
```Swift
@@ -111,17 +110,17 @@ class MyViewController : UIViewController {
111110
}
112111
``` -->
113112

114-
<!-- > -->
113+
<!-- v -->
115114

116-
2. **Massive View Controller Problem** &mdash; (see previous lesson for description and example)
115+
2. **Massive View Controller Problem**
117116

118117
3. **Reusability** &mdash; with standard MVC, View Controllers are nearly impossible to reuse, especially if overloaded with non-VC tasks.
119118

120119
4. **Tight Coupling** &mdash; an inflexible design in which every controller needs to know details about other controllers inhibits an app's growth.
121120

122-
<!-- > -->
121+
<!-- v -->
123122

124-
5. **Deep Linking Issues** &mdash; *(see Coordinators and Deep Linking section)*
123+
5. **Deep Linking Issues**
125124

126125
6. **Testing** &mdash; if you want to generate different views or a different flow in response to user choices (A/B testing) or to handle layout variations, standard MVC implementations of VCs make it extremely difficult to test those scenarios.
127126

@@ -130,9 +129,7 @@ class MyViewController : UIViewController {
130129
### Implementation Notes
131130

132131
A solid, basic implementation of coordinators includes 3 main steps:
133-
1. Design two protocols:
134-
- __*Coordinator Protocol*__ - To be used by all our coordinators.
135-
- __*View Controller Creation Protocol*__ - To facilitate view controller creation.
132+
1. Design a **Coordinator protocol**
136133
2. Create a __*main coordinator*__ that will control app flow. Start it when your app launches.
137134
3. Create/present view controllers.
138135

@@ -141,13 +138,12 @@ A solid, basic implementation of coordinators includes 3 main steps:
141138
**About the Coordinator Protocol**
142139

143140
All coordinators will conform to this protocol. At bare minimum, it should include:
144-
- A property to store any **child coordinators**. Coordinator responsibility is to **handle navigation flow**: the same way that UINavigationController keeps reference of its stack, Coordinators do the same with their children. (optional)
145-
- A property to store the **navigation controller** being used to present view controllers. (Even if you don’t show the navigation bar at the top, using a navigation controller is the easiest way to present view controllers.)
141+
- A property to store the **navigation controller** being used to present view controllers.
146142
- A `start()` function to make the coordinator take control. This allows us to create a coordinator fully and activate it only when we’re ready.
143+
- A property to store any **child coordinators**. Coordinator responsibility is to **handle navigation flow**: the same way that UINavigationController keeps reference of its stack, Coordinators do the same with their children. (optional)
147144

148145
<!-- > -->
149146

150-
151147
#### Example:
152148

153149
1. Coordinator protocol created
@@ -156,7 +152,7 @@ All coordinators will conform to this protocol. At bare minimum, it should inclu
156152
protocol Coordinator {
157153
func start()
158154
var navigationController: UINavigationController { get set }
159-
var childCoordinators : [Coordinator] { get set } //not always
155+
//var childCoordinators : [Coordinator] { get set }
160156
}
161157
```
162158

@@ -165,7 +161,9 @@ protocol Coordinator {
165161
2. For building the user flow, a concrete implementation of the protocol is created:
166162

167163
```Swift
168-
class BaseCoordinator: Coordinator {
164+
class MainCoordinator: Coordinator {
165+
166+
//var childCoordinators: [Coordinator] = []
169167

170168
var navigationController: UINavigationController
171169
private var someViewController: UIViewController?
@@ -185,60 +183,58 @@ class BaseCoordinator: Coordinator {
185183
<!-- > -->
186184

187185
3. All view controllers targeted for participation in the coordinated navigation approach must:
188-
- Have a `BaseCoordinator` property for access to its properties and functions
186+
- Have a `MainCoordinator` property for access to its properties and functions
189187

190188
```Swift
191189
class ViewController: UIViewController {
192190

193-
var coordinator: BaseCoordinator?
191+
var coordinator: MainCoordinator?
194192
...
195193
}
196194
```
197195

198196
<!-- > -->
199197

200-
5. If staring from the AppDelegate:
198+
5. If staring from the SceneDelegate:
201199

202200
```swift
201+
guard let windowScene = (scene as? UIWindowScene) else { return }
202+
203+
var coordinator: MainCoordinator?
204+
203205
let navController = UINavigationController()
204-
coordinator = BaseCoordinator(navigationController: navController)
206+
coordinator = MainCoordinator(navigationController: navController)
205207
coordinator?.start()
206208

207-
window = UIWindow(frame: UIScreen.main.bounds)
208-
window?.rootViewController = navController
209-
window?.makeKeyAndVisible()
209+
window = UIWindow(windowScene: windowScene)
210+
window!.rootViewController = navController
211+
window!.makeKeyAndVisible()
210212
```
211213

212214
<!-- > -->
213215

214-
##Practicing a simple approach
216+
## Practicing the simple approach
215217

216-
Follow [these instructions]() to create a flow using coordinators.
218+
Code Demo
217219

218220
<!-- > -->
219221

220222
## Benefits
221223

222-
They can have huge impact on cleaning the code base and on making view controllers more loosely coupled from each other.
223-
224-
The pattern can be adopted for only part of an app or used across the entire application.
225-
226-
<!-- > -->
227-
228224
Coordinators create a well defined way to deal with navigation in which view controllers are:
229225
1. Isolated from each other (do not need to know about each other)
230-
2. Reusable in different contexts
231-
3. Lightweight, less "massive," and focused on their key responsibilities
226+
2. Reusable
227+
3. Lightweight and focused on their key responsibilities
232228

233229
<!-- > -->
234230

235231
## Pitfalls
236232

237233
The downside of the Coordinator pattern:
238234

239-
1. **Back Button Issue** &mdash; When the user navigates back, developers must ensure that the right coordinator is released. Solutions for this might come with potential loss of built-in framework features.
235+
1. More code 😅
240236

241-
2. **Overkill** &mdash; The pattern could well take too much work for very simple apps. Many extra classes will need to be created upfront.
237+
2. Can get complex as the app goes to deeper levels in the stack
242238

243239
<!-- > -->
244240

@@ -259,14 +255,14 @@ This requires one high-level coordinator instantiated in the `AppDelegate` that
259255

260256
The `AppCoordinator` holds an array of child coordinators, who in turn might hold an array of their own child coordinators.
261257

262-
This is especially useful in a TabBar app: each TabBar scene's navigation controller could get its own coordinator for directing its own behavior and flow. And each coordinator can be spawned by its parent coordinator.
258+
This is especially useful in a **TabBar** app: each TabBar scene's navigation controller could get its own coordinator for directing its own behavior and flow. And each coordinator can be spawned by its parent coordinator.
263259

264260
<!-- > -->
265261

266262
![example](assets/coordinator_types2.png)
267263

268-
*Source:* </br>
269-
https://www.scoop.it/topic/swift-by-jerometonnelier/p/4097595680/2018/05/11/the-c-in-mvvm-c-mihael-y-cholakov
264+
[Source](https://www.scoop.it/topic/swift-by-jerometonnelier/p/4097595680/2018/05/11/the-c-in-mvvm-c-mihael-y-cholakov)
265+
270266

271267
<!-- > -->
272268

@@ -284,26 +280,17 @@ A common way to do this on iOS is to define a URL scheme that other apps can the
284280

285281
<!-- > -->
286282

287-
__*The Obstacle*__
288-
289-
To support deep linking in an iOS app, you might need to open specific views in the app, regardless of the navigation history or navigation design.
290-
291-
With standard MVC and its potential to tightly-couple View Controllers, it is very difficult to implement deep linking.
292-
293-
<!-- > -->
294-
295283
__*The Solution*__
296284

297285
Using Coordinators and navigator objects, implementing URL and deep linking support becomes a lot easier because it allows for dedicated navigation points in which URL handling logic can be injected.
298286

299287
*from:*
300288
https://medium.com/@abhimuralidharan/universal-links-in-ios-79c4ee038272
301289

302-
<!-- this needs some example TODO: research this more -->
303290

304291
<!-- > -->
305292

306-
### Coordinator &mdash; with Other Patterns
293+
### Coordinator &mdash; with other patterns
307294

308295
Coordinator is an easy pattern to implement with other complementary patterns.
309296

@@ -319,7 +306,21 @@ For examples:
319306

320307
<!-- > -->
321308

322-
## In Class Activity
309+
## In - Class Activity
310+
311+
TabBar App using Coordinators
312+
313+
<!-- > -->
314+
315+
## Useful library
316+
317+
[Coordinator Library](https://github.com/daveneff/Coordinator)
318+
319+
[TabBar implementation using library](https://github.com/levibostian/TabBar-Coordinator-example)
320+
321+
<!-- > -->
322+
323+
## Stretch Challenge
323324

324325
Download [this starter code](https://github.com/alfianlosari/MovieCoordinator-Starter-Project)
325326

@@ -338,19 +339,12 @@ protocol Coordinator {
338339

339340
<!-- > -->
340341

341-
### Stretch Challenges
342-
343-
This exercise follows on today's Activity 1...
344-
345-
**Resources Required** Your completed app from Activity 1
346-
347-
**TODO:** In the tutorial below, complete these sections:
342+
## Lab
348343

349-
- "How and when to use child coordinators"
350-
- "Navigating backwards"
351-
- "Passing data between view controllers"
344+
Watch [this presentation](https://youtu.be/9VojuJpUuE8) on MVVM-C.
345+
-[source](https://github.com/macdevnet/mvvmc-demo)
352346

353-
[Advanced coordinators in iOS - a tutorial](https://www.hackingwithswift.com/articles/175/advanced-coordinator-pattern-tutorial-ios)
347+
Draw the architectural diagram of MVVM-C, mentioning responsibilities and main properties.
354348

355349
<!-- > -->
356350

@@ -360,18 +354,16 @@ This exercise follows on today's Activity 1...
360354

361355
- Application Coordinator Pattern
362356
- Router (with Coordinators)
363-
- Data Source Design Pattern
364357
- Deep Linking (specific to iOS)
365358
- `Universal Link`
366-
- State Machine
367359
- MVP
368360

369361
<!-- > -->
370362

371363
## Additional Resources
372364

373365
1. [Slides](https://docs.google.com/presentation/d/1Ny2GlorCMgeJdkNo7AZg3m_SH4FwBLyFnrbh9Twqk4o/edit#slide=id.g50e0c2788f_27_8)
374-
2. [The Coordinator - an aricle ](http://khanlou.com/2015/01/the-coordinator/), by Soroush Khanlou, <sup>1</sup> who popularized the pattern for iOS development.
366+
2. [The Coordinator - an article ](http://khanlou.com/2015/01/the-coordinator/), by Soroush Khanlou, <sup>1</sup> who popularized the pattern for iOS development.
375367
3. [Coordinators - video presentation](https://vimeo.com/144116310)
376368
4. [Coordinators - a slideshare from LinkedIn](https://www.slideshare.net/secret/3jJlEE1weo0RRl)
377369
5. [8 Patterns to Help You Destroy Massive View Controller - an article](http://khanlou.com/2014/09/8-patterns-to-help-you-destroy-massive-view-controller/)
@@ -386,7 +378,7 @@ This exercise follows on today's Activity 1...
386378

387379

388380

389-
<!-- INSTRUCTOR NOTES: SOLUTION TO ACTIVITY 1
381+
<!-- INSTRUCTOR: SOLUTION TO ACTIVITY 1
390382
391383
PART 1: IN App Delegate:
392384
-93.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)