-
Notifications
You must be signed in to change notification settings - Fork 184
/
Copy pathindex.html
601 lines (512 loc) · 55.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
<!DOCTYPE html>
<html lang="en">
<head>
<title>XCoordinator Reference</title>
<link rel="stylesheet" type="text/css" href="css/jazzy.css" />
<link rel="stylesheet" type="text/css" href="css/highlight.css" />
<meta charset="utf-8">
<script src="js/jquery.min.js" defer></script>
<script src="js/jazzy.js" defer></script>
<script src="js/lunr.min.js" defer></script>
<script src="js/typeahead.jquery.js" defer></script>
<script src="js/jazzy.search.js" defer></script>
</head>
<body>
<a title="XCoordinator Reference"></a>
<header class="header">
<p class="header-col header-col--primary">
<a class="header-link" href="index.html">
XCoordinator Docs
</a>
</p>
<p class="header-col--secondary">
<form role="search" action="search.json">
<input type="text" placeholder="Search documentation" data-typeahead>
</form>
</p>
<p class="header-col header-col--secondary">
<a class="header-link" href="https://github.com/quickbirdstudios/XCoordinator">
<img class="header-icon" src="img/gh.png"/>
View on GitHub
</a>
</p>
</header>
<p class="breadcrumbs">
<a class="breadcrumb" href="index.html">XCoordinator Reference</a>
<img class="carat" src="img/carat.png" />
XCoordinator Reference
</p>
<div class="content-wrapper">
<nav class="navigation">
<ul class="nav-groups">
<li class="nav-group-name">
<a class="nav-group-name-link" href="Classes.html">Classes</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/Animation.html">Animation</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/AnyCoordinator.html">AnyCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/AnyTransitionPerformer.html">AnyTransitionPerformer</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/BaseCoordinator.html">BaseCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/BasicCoordinator.html">BasicCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/BasicCoordinator/InitialLoadingType.html">– InitialLoadingType</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/InteractiveTransitionAnimation.html">InteractiveTransitionAnimation</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/InterruptibleTransitionAnimation.html">InterruptibleTransitionAnimation</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/NavigationAnimationDelegate.html">NavigationAnimationDelegate</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/NavigationCoordinator.html">NavigationCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/PageCoordinator.html">PageCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/PageCoordinatorDataSource.html">PageCoordinatorDataSource</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/RedirectionRouter.html">RedirectionRouter</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/SplitCoordinator.html">SplitCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/StaticTransitionAnimation.html">StaticTransitionAnimation</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/StrongRouter.html">StrongRouter</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/TabBarAnimationDelegate.html">TabBarAnimationDelegate</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/TabBarCoordinator.html">TabBarCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Classes/ViewCoordinator.html">ViewCoordinator</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a class="nav-group-name-link" href="Extensions.html">Extensions</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a class="nav-group-task-link" href="Extensions/UIView.html">UIView</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Extensions/UIViewController.html">UIViewController</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a class="nav-group-name-link" href="Protocols.html">Protocols</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/Container.html">Container</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/Coordinator.html">Coordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/PercentDrivenInteractionController.html">PercentDrivenInteractionController</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/Presentable.html">Presentable</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols.html#/s:12XCoordinator5RouteP">Route</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/Router.html">Router</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/TransitionAnimation.html">TransitionAnimation</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/TransitionContext.html">TransitionContext</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/TransitionPerformer.html">TransitionPerformer</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Protocols/TransitionProtocol.html">TransitionProtocol</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a class="nav-group-name-link" href="Structs.html">Structures</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a class="nav-group-task-link" href="Structs/Transition.html">Transition</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Structs/TransitionOptions.html">TransitionOptions</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Structs/UnownedErased.html">UnownedErased</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Structs/UnownedErased.html">UnownedErased</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Structs/WeakErased.html">WeakErased</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Structs/WeakErased.html">WeakErased</a>
</li>
</ul>
</li>
<li class="nav-group-name">
<a class="nav-group-name-link" href="Typealiases.html">Type Aliases</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator24AnyNavigationCoordinatora">AnyNavigationCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator9AnyRoutera">AnyRouter</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator20AnyTabBarCoordinatora">AnyTabBarCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator18AnyViewCoordinatora">AnyViewCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator26BasicNavigationCoordinatora">BasicNavigationCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator22BasicTabBarCoordinatora">BasicTabBarCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator20BasicViewCoordinatora">BasicViewCoordinator</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator26ContextPresentationHandlera">ContextPresentationHandler</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator20NavigationTransitiona">NavigationTransition</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator14PageTransitiona">PageTransition</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator19PresentationHandlera">PresentationHandler</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator15SplitTransitiona">SplitTransition</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator16TabBarTransitiona">TabBarTransition</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator13UnownedRoutera">UnownedRouter</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator14ViewTransitiona">ViewTransition</a>
</li>
<li class="nav-group-task">
<a class="nav-group-task-link" href="Typealiases.html#/s:12XCoordinator10WeakRoutera">WeakRouter</a>
</li>
</ul>
</li>
</ul>
</nav>
<article class="main-content">
<section class="section">
<div class="section-content">
<p align="center">
<img src="https://quickbirdstudios.com/files/xcoordinator/logo.png">
</p>
<h1 id='a-href-https-travis-ci-com-quickbirdstudios-xcoordinator-img-src-https-travis-ci-com-quickbirdstudios-xcoordinator-svg-branch-master-alt-build-status-a-a-href-https-cocoapods-org-pods-xcoordinator-img-src-https-img-shields-io-cocoapods-v-xcoordinator-svg-alt-cocoapods-compatible-a-a-href-https-github-com-carthage-carthage-img-src-https-img-shields-io-badge-carthage-compatible-4bc51d-svg-style-flat-alt-carthage-compatible-a-a-href-https-quickbirdstudios-github-io-xcoordinator-img-src-https-github-com-quickbirdstudios-xcoordinator-blob-master-docs-badge-svg-alt-documentation-a-a-href-https-github-com-quickbirdstudios-xcoordinator-img-src-https-img-shields-io-badge-platform-ios-lightgrey-svg-alt-platform-a-a-href-https-github-com-quickbirdstudios-xcoordinator-blob-master-license-img-src-https-img-shields-io-cocoapods-l-xcoordinator-svg-alt-license-a' class='heading'><a href="https://travis-ci.com/quickbirdstudios/XCoordinator"><img src="https://travis-ci.com/quickbirdstudios/XCoordinator.svg?branch=master" alt="Build Status"></a> <a href="https://cocoapods.org/pods/XCoordinator"><img src="https://img.shields.io/cocoapods/v/XCoordinator.svg" alt="CocoaPods Compatible"></a> <a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat" alt="Carthage Compatible"></a> <a href="https://quickbirdstudios.github.io/XCoordinator"><img src="https://github.com/quickbirdstudios/XCoordinator/blob/master/docs/badge.svg" alt="Documentation"></a> <a href="https://github.com/quickbirdstudios/XCoordinator"><img src="https://img.shields.io/badge/platform-iOS-lightgrey.svg" alt="Platform"></a> <a href="https://github.com/quickbirdstudios/XCoordinator/blob/master/LICENSE"><img src="https://img.shields.io/cocoapods/l/XCoordinator.svg" alt="License"></a></h1>
<p>⚠️ We have recently released XCoordinator 2.0. Make sure to read <a href="#when-to-use-which-router-abstraction">this section</a> before migrating. In general, please replace all <code><a href="Typealiases.html#/s:12XCoordinator9AnyRoutera">AnyRouter</a></code> by either <code><a href="Typealiases.html#/s:12XCoordinator13UnownedRoutera">UnownedRouter</a></code> (in viewControllers, viewModels or references to parent coordinators) or <code><a href="Classes/StrongRouter.html">StrongRouter</a></code> in your <code>AppDelegate</code> or for references to child coordinators. In addition to that, the rootViewController is now injected into the initializer instead of being created in the <code>Coordinator.generateRootViewController</code> method.</p>
<p>“How does an app transition from one view controller to another?”.
This question is common and puzzling regarding iOS development. There are many answers, as every architecture has different implementation variations. Some do it from within the implementation of a view controller, while some use a router/coordinator, an object connecting view models.</p>
<p>To better answer the question, we are building <strong>XCoordinator</strong>, a navigation framework based on the <strong>Coordinator</strong> pattern.
It’s especially useful for implementing MVVM-C, Model-View-ViewModel-Coordinator:</p>
<p align="center">
<img src="https://quickbirdstudios.com/files/xcoordinator/mvvmc.png">
</p>
<h2 id='️getting-started' class='heading'>🏃♂️Getting started</h2>
<p>Create an enum with all of the navigation paths for a particular flow, i.e. a group of closely connected scenes. (It is up to you when to create a <code>Route/Coordinator</code>. As <strong>our rule of thumb</strong>, create a new <code>Route/Coordinator</code> whenever a new root view controller, e.g. a new <code>navigation controller</code> or a <code>tab bar controller</code>, is needed.).</p>
<p>Whereas the <code><a href="Protocols.html#/s:12XCoordinator5RouteP">Route</a></code> describes which routes can be triggered in a flow, the <code><a href="Protocols/Coordinator.html">Coordinator</a></code> is responsible for the preparation of transitions based on routes being triggered. We could, therefore, prepare multiple coordinators for the same route, which differ in which transitions are executed for each route.</p>
<p>In the following example, we create the <code>UserListRoute</code> enum to define triggers of a flow of our application. <code>UserListRoute</code> offers routes to open the home screen, display a list of users, to open a specific user and to log out. The <code>UserListCoordinator</code> is implemented to prepare transitions for the triggered routes. When a <code>UserListCoordinator</code> is shown, it triggers the <code>.home</code> route to display a <code>HomeViewController</code>.</p>
<pre class="highlight swift"><code><span class="kd">enum</span> <span class="kt">UserListRoute</span><span class="p">:</span> <span class="kt">Route</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">home</span>
<span class="k">case</span> <span class="n">users</span>
<span class="k">case</span> <span class="nf">user</span><span class="p">(</span><span class="kt">String</span><span class="p">)</span>
<span class="k">case</span> <span class="nf">registerUsersPeek</span><span class="p">(</span><span class="nv">from</span><span class="p">:</span> <span class="kt">Container</span><span class="p">)</span>
<span class="k">case</span> <span class="n">logout</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="kt">UserListCoordinator</span><span class="p">:</span> <span class="kt">NavigationCoordinator</span><span class="o"><</span><span class="kt">UserListRoute</span><span class="o">></span> <span class="p">{</span>
<span class="nf">init</span><span class="p">()</span> <span class="p">{</span>
<span class="k">super</span><span class="o">.</span><span class="nf">init</span><span class="p">(</span><span class="nv">initialRoute</span><span class="p">:</span> <span class="o">.</span><span class="n">home</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">prepareTransition</span><span class="p">(</span><span class="k">for</span> <span class="nv">route</span><span class="p">:</span> <span class="kt">UserListRoute</span><span class="p">)</span> <span class="o">-></span> <span class="kt">NavigationTransition</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">route</span> <span class="p">{</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">home</span><span class="p">:</span>
<span class="k">let</span> <span class="nv">viewController</span> <span class="o">=</span> <span class="kt">HomeViewController</span><span class="o">.</span><span class="nf">instantiateFromNib</span><span class="p">()</span>
<span class="k">let</span> <span class="nv">viewModel</span> <span class="o">=</span> <span class="kt">HomeViewModelImpl</span><span class="p">(</span><span class="nv">router</span><span class="p">:</span> <span class="n">anyRouter</span><span class="p">)</span>
<span class="n">viewController</span><span class="o">.</span><span class="nf">bind</span><span class="p">(</span><span class="nv">to</span><span class="p">:</span> <span class="n">viewModel</span><span class="p">)</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="n">viewController</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">users</span><span class="p">:</span>
<span class="k">let</span> <span class="nv">viewController</span> <span class="o">=</span> <span class="kt">UsersViewController</span><span class="o">.</span><span class="nf">instantiateFromNib</span><span class="p">()</span>
<span class="k">let</span> <span class="nv">viewModel</span> <span class="o">=</span> <span class="kt">UsersViewModelImpl</span><span class="p">(</span><span class="nv">router</span><span class="p">:</span> <span class="n">anyRouter</span><span class="p">)</span>
<span class="n">viewController</span><span class="o">.</span><span class="nf">bind</span><span class="p">(</span><span class="nv">to</span><span class="p">:</span> <span class="n">viewModel</span><span class="p">)</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="n">viewController</span><span class="p">,</span> <span class="nv">animation</span><span class="p">:</span> <span class="o">.</span><span class="n">interactiveFade</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nf">user</span><span class="p">(</span><span class="k">let</span> <span class="nv">username</span><span class="p">):</span>
<span class="k">let</span> <span class="nv">coordinator</span> <span class="o">=</span> <span class="kt">UserCoordinator</span><span class="p">(</span><span class="nv">user</span><span class="p">:</span> <span class="n">username</span><span class="p">)</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">present</span><span class="p">(</span><span class="n">coordinator</span><span class="p">,</span> <span class="nv">animation</span><span class="p">:</span> <span class="o">.</span><span class="k">default</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nf">registerUsersPeek</span><span class="p">(</span><span class="k">let</span> <span class="nv">source</span><span class="p">):</span>
<span class="k">return</span> <span class="nf">registerPeek</span><span class="p">(</span><span class="nv">for</span><span class="p">:</span> <span class="n">source</span><span class="p">,</span> <span class="nv">route</span><span class="p">:</span> <span class="o">.</span><span class="n">users</span><span class="p">)</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">logout</span><span class="p">:</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">dismiss</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>Routes are triggered from within Coordinators or ViewModels. In the following, we describe how to trigger routes from within a ViewModel. The router of the current flow is injected into the ViewModel.</p>
<pre class="highlight swift"><code><span class="kd">class</span> <span class="kt">HomeViewModel</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">router</span><span class="p">:</span> <span class="kt">UnownedRouter</span><span class="o"><</span><span class="kt">HomeRoute</span><span class="o">></span>
<span class="nf">init</span><span class="p">(</span><span class="nv">router</span><span class="p">:</span> <span class="kt">UnownedRouter</span><span class="o"><</span><span class="kt">HomeRoute</span><span class="o">></span><span class="p">)</span> <span class="p">{</span>
<span class="k">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">router</span>
<span class="p">}</span>
<span class="cm">/* ... */</span>
<span class="kd">func</span> <span class="nf">usersButtonPressed</span><span class="p">()</span> <span class="p">{</span>
<span class="n">router</span><span class="o">.</span><span class="nf">trigger</span><span class="p">(</span><span class="o">.</span><span class="n">users</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<h3 id='organizing-an-app-39-s-structure-with-xcoordinator' class='heading'>🏗 Organizing an app’s structure with XCoordinator</h3>
<p>In general, an app’s structure is defined by nesting coordinators and view controllers. You can transition (i.e. <code>push</code>, <code>present</code>, <code>pop</code>, <code>dismiss</code>) to a different coordinator whenever your app changes to a different flow. Within a flow, we transition between viewControllers.</p>
<p>Example: In <code>UserListCoordinator.prepareTransition(for:)</code> we change from the <code>UserListRoute</code> to the <code>UserRoute</code> whenever the <code>UserListRoute.user</code> route is triggered. By dismissing a viewController in <code>UserListRoute.logout</code>, we additionally switch back to the previous flow - in this case the <code>HomeRoute</code>.</p>
<p>To achieve this behavior, every Coordinator has its own <code>rootViewController</code>. This would be a <code>UINavigationController</code> in the case of a <code><a href="Classes/NavigationCoordinator.html">NavigationCoordinator</a></code>, a <code>UITabBarController</code> in the case of a <code><a href="Classes/TabBarCoordinator.html">TabBarCoordinator</a></code>, etc. When transitioning to a Coordinator/Router, this <code>rootViewController</code> is used as the destination view controller.</p>
<h3 id='using-xcoordinator-from-app-launch' class='heading'>🏁 Using XCoordinator from App Launch</h3>
<p>To use coordinators from the launch of the app, make sure to create the app’s <code>window</code> programmatically in <code>AppDelegate.swift</code> (Don’t forget to remove <code>Main Storyboard file base name</code> from <code>Info.plist</code>). Then, set the coordinator as the root of the <code>window</code>‘s view hierarchy in the <code>AppDelegate.didFinishLaunching</code>. Make sure to hold a strong reference to your app’s initial coordinator or a <code>strongRouter</code> reference.</p>
<pre class="highlight swift"><code><span class="kd">@UIApplicationMain</span>
<span class="kd">class</span> <span class="kt">AppDelegate</span><span class="p">:</span> <span class="kt">UIResponder</span><span class="p">,</span> <span class="kt">UIApplicationDelegate</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">window</span><span class="p">:</span> <span class="kt">UIWindow</span><span class="o">!</span> <span class="o">=</span> <span class="kt">UIWindow</span><span class="p">()</span>
<span class="k">let</span> <span class="nv">router</span> <span class="o">=</span> <span class="kt">AppCoordinator</span><span class="p">()</span><span class="o">.</span><span class="n">strongRouter</span>
<span class="kd">func</span> <span class="nf">application</span><span class="p">(</span><span class="n">_</span> <span class="nv">application</span><span class="p">:</span> <span class="kt">UIApplication</span><span class="p">,</span> <span class="n">didFinishLaunchingWithOptions</span> <span class="nv">launchOptions</span><span class="p">:</span> <span class="p">[</span><span class="kt">UIApplicationLaunchOptionsKey</span><span class="p">:</span> <span class="kt">Any</span><span class="p">]?)</span> <span class="o">-></span> <span class="kt">Bool</span> <span class="p">{</span>
<span class="n">router</span><span class="o">.</span><span class="nf">setRoot</span><span class="p">(</span><span class="nv">for</span><span class="p">:</span> <span class="n">window</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<h2 id='️-extras' class='heading'>🤸♂️ Extras</h2>
<p>For more advanced use, XCoordinator offers many more customization options. We introduce custom animated transitions and deep linking. Furthermore, extensions for use in reactive programming with RxSwift/Combine and options to split up huge routes are described.</p>
<h3 id='custom-transitions' class='heading'>🌗 Custom Transitions</h3>
<p>Custom animated transitions define presentation and dismissal animations. You can specify <code><a href="Classes/Animation.html">Animation</a></code> objects in <code>prepareTransition(for:)</code> in your coordinator for several common transitions, such as <code>present</code>, <code>dismiss</code>, <code>push</code> and <code>pop</code>. Specifying no animation (<code>nil</code>) results in not overriding previously set animations. Use <code><a href="Classes/Animation.html#/s:12XCoordinator9AnimationC7defaultACvpZ">Animation.default</a></code> to reset previously set animation to the default animations UIKit offers.</p>
<pre class="highlight swift"><code><span class="kd">class</span> <span class="kt">UsersCoordinator</span><span class="p">:</span> <span class="kt">NavigationCoordinator</span><span class="o"><</span><span class="kt">UserRoute</span><span class="o">></span> <span class="p">{</span>
<span class="cm">/* ... */</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">prepareTransition</span><span class="p">(</span><span class="k">for</span> <span class="nv">route</span><span class="p">:</span> <span class="kt">UserRoute</span><span class="p">)</span> <span class="o">-></span> <span class="kt">NavigationTransition</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">route</span> <span class="p">{</span>
<span class="k">case</span> <span class="o">.</span><span class="nf">user</span><span class="p">(</span><span class="k">let</span> <span class="nv">name</span><span class="p">):</span>
<span class="k">let</span> <span class="nv">animation</span> <span class="o">=</span> <span class="kt">Animation</span><span class="p">(</span>
<span class="nv">presentationAnimation</span><span class="p">:</span> <span class="kt">YourAwesomePresentationTransitionAnimation</span><span class="p">(),</span>
<span class="nv">dismissalAnimation</span><span class="p">:</span> <span class="kt">YourAwesomeDismissalTransitionAnimation</span><span class="p">()</span>
<span class="p">)</span>
<span class="k">let</span> <span class="nv">viewController</span> <span class="o">=</span> <span class="kt">UserViewController</span><span class="o">.</span><span class="nf">instantiateFromNib</span><span class="p">()</span>
<span class="k">let</span> <span class="nv">viewModel</span> <span class="o">=</span> <span class="kt">UserViewModelImpl</span><span class="p">(</span><span class="nv">coordinator</span><span class="p">:</span> <span class="n">coordinator</span><span class="p">,</span> <span class="nv">name</span><span class="p">:</span> <span class="n">name</span><span class="p">)</span>
<span class="n">viewController</span><span class="o">.</span><span class="nf">bind</span><span class="p">(</span><span class="nv">to</span><span class="p">:</span> <span class="n">viewModel</span><span class="p">)</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="n">viewController</span><span class="p">,</span> <span class="nv">animation</span><span class="p">:</span> <span class="n">animation</span><span class="p">)</span>
<span class="cm">/* ... */</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<h3 id='deep-linking' class='heading'>🛤 Deep Linking</h3>
<p>Deep Linking can be used to chain different routes together. In contrast to the <code>.multiple</code> transition, deep linking can identify routers based on previous transitions (e.g. when pushing or presenting a router), which enables chaining of routes of different types. Keep in mind, that you cannot access higher-level routers anymore once you trigger a route on a lower level of the router hierarchy.</p>
<pre class="highlight swift"><code><span class="kd">class</span> <span class="kt">AppCoordinator</span><span class="p">:</span> <span class="kt">NavigationCoordinator</span><span class="o"><</span><span class="kt">AppRoute</span><span class="o">></span> <span class="p">{</span>
<span class="cm">/* ... */</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">prepareTransition</span><span class="p">(</span><span class="k">for</span> <span class="nv">route</span><span class="p">:</span> <span class="kt">AppRoute</span><span class="p">)</span> <span class="o">-></span> <span class="kt">NavigationTransition</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">route</span> <span class="p">{</span>
<span class="cm">/* ... */</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">deep</span><span class="p">:</span>
<span class="k">return</span> <span class="nf">deepLink</span><span class="p">(</span><span class="kt">AppRoute</span><span class="o">.</span><span class="n">login</span><span class="p">,</span> <span class="kt">AppRoute</span><span class="o">.</span><span class="n">home</span><span class="p">,</span> <span class="kt">HomeRoute</span><span class="o">.</span><span class="n">news</span><span class="p">,</span> <span class="kt">HomeRoute</span><span class="o">.</span><span class="n">dismiss</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>⚠️ XCoordinator does not check at compile-time, whether a deep link can be executed. Rather it uses assertionFailures to inform about incorrect chaining at runtime, when it cannot find an appriopriate router for a given route. Keep this in mind when changing the structure of your app.</p>
<h3 id='redirectionrouter' class='heading'>🚏 RedirectionRouter</h3>
<p>Let’s assume, there is a route type called <code>HugeRoute</code> with more than 10 routes. To decrease coupling, <code>HugeRoute</code> needs to be split up into mutliple route types. As you will discover, many routes in <code>HugeRoute</code> use transitions dependent on a specific rootViewController, such as <code>push</code>, <code>show</code>, <code>pop</code>, etc. If splitting up routes by introducing a new router/coordinator is not an option, XCoordinator has two solutions for you to solve such a case: <code><a href="Classes/RedirectionRouter.html">RedirectionRouter</a></code> or using multiple coordinators with the same rootViewController (<a href="#using-multiple-coordinators-with-the-same-rootviewcontroller">see this section for more information</a>).</p>
<p>A <code><a href="Classes/RedirectionRouter.html">RedirectionRouter</a></code> can be used to map a new route type onto a generalized <code>ParentRoute</code>. A <code><a href="Classes/RedirectionRouter.html">RedirectionRouter</a></code> is independent of the <code>TransitionType</code> of its parent router. You can use <code><a href="Classes/RedirectionRouter.html#/s:12XCoordinator17RedirectionRouterC14viewController6parent3mapACyxq_GSo06UIViewE0C_AA13UnownedErasedVyAA06StrongC0CyxGGxq_cSgtcfc">RedirectionRouter.init(viewController:parent:map:)</a></code> or subclassing by overriding <code>mapToParentRoute(_:)</code> to create a <code><a href="Classes/RedirectionRouter.html">RedirectionRouter</a></code>.</p>
<p>The following code example illustrates how a <code><a href="Classes/RedirectionRouter.html">RedirectionRouter</a></code> is initialized and used.</p>
<pre class="highlight swift"><code><span class="kd">class</span> <span class="kt">ParentCoordinator</span><span class="p">:</span> <span class="kt">NavigationCoordinator</span><span class="o"><</span><span class="kt">ParentRoute</span><span class="o">></span> <span class="p">{</span>
<span class="cm">/* ... */</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">prepareTransition</span><span class="p">(</span><span class="k">for</span> <span class="nv">route</span><span class="p">:</span> <span class="kt">ParentRoute</span><span class="p">)</span> <span class="o">-></span> <span class="kt">NavigationTransition</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">route</span> <span class="p">{</span>
<span class="cm">/* ... */</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">subCoordinator</span><span class="p">:</span>
<span class="k">let</span> <span class="nv">subCoordinator</span> <span class="o">=</span> <span class="kt">SubCoordinator</span><span class="p">(</span><span class="nv">parent</span><span class="p">:</span> <span class="n">unownedRouter</span><span class="p">)</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">push</span><span class="p">(</span><span class="n">subCoordinator</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="kt">ChildCoordinator</span><span class="p">:</span> <span class="kt">RedirectionRouter</span><span class="o"><</span><span class="kt">ParentRoute</span><span class="p">,</span> <span class="kt">ChildRoute</span><span class="o">></span> <span class="p">{</span>
<span class="nf">init</span><span class="p">(</span><span class="nv">parent</span><span class="p">:</span> <span class="kt">UnownedRouter</span><span class="o"><</span><span class="kt">ParentRoute</span><span class="o">></span><span class="p">)</span> <span class="p">{</span>
<span class="k">let</span> <span class="nv">viewController</span> <span class="o">=</span> <span class="kt">UIViewController</span><span class="p">()</span>
<span class="c1">// this viewController is used when performing transitions with the Subcoordinator directly.</span>
<span class="k">super</span><span class="o">.</span><span class="nf">init</span><span class="p">(</span><span class="nv">viewController</span><span class="p">:</span> <span class="n">viewController</span><span class="p">,</span> <span class="nv">parent</span><span class="p">:</span> <span class="n">parent</span><span class="p">,</span> <span class="nv">map</span><span class="p">:</span> <span class="kc">nil</span><span class="p">)</span>
<span class="p">}</span>
<span class="cm">/* ... */</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">mapToSuperRoute</span><span class="p">(</span><span class="k">for</span> <span class="nv">route</span><span class="p">:</span> <span class="kt">ChildRoute</span><span class="p">)</span> <span class="o">-></span> <span class="kt">ParentRoute</span> <span class="p">{</span>
<span class="c1">// you can map your ChildRoute enum to ParentRoute cases here that will get triggered on the parent router.</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<h3 id='using-multiple-coordinators-with-the-same-rootviewcontroller' class='heading'>🚏Using multiple coordinators with the same rootViewController</h3>
<p>With XCoordinator 2.0, we introduce the option to use different coordinators with the same rootViewController.
Since you can specify the rootViewController in the initializer of a new coordinator, you can specify an existing coordinator’s rootViewController as in the following:</p>
<pre class="highlight swift"><code><span class="kd">class</span> <span class="kt">FirstCoordinator</span><span class="p">:</span> <span class="kt">NavigationCoordinator</span><span class="o"><</span><span class="kt">FirstRoute</span><span class="o">></span> <span class="p">{</span>
<span class="cm">/* ... */</span>
<span class="k">override</span> <span class="kd">func</span> <span class="nf">prepareTransition</span><span class="p">(</span><span class="k">for</span> <span class="nv">route</span><span class="p">:</span> <span class="kt">FirstRoute</span><span class="p">)</span> <span class="o">-></span> <span class="kt">NavigationTransition</span> <span class="p">{</span>
<span class="k">switch</span> <span class="n">route</span> <span class="p">{</span>
<span class="k">case</span> <span class="o">.</span><span class="nv">secondCoordinator</span><span class="p">:</span>
<span class="k">let</span> <span class="nv">secondCoordinator</span> <span class="o">=</span> <span class="kt">SecondCoordinator</span><span class="p">(</span><span class="nv">rootViewController</span><span class="p">:</span> <span class="k">self</span><span class="o">.</span><span class="n">rootViewController</span><span class="p">)</span>
<span class="nf">addChild</span><span class="p">(</span><span class="n">secondCoordinator</span><span class="p">)</span>
<span class="k">return</span> <span class="o">.</span><span class="nf">none</span><span class="p">()</span>
<span class="c1">// you could also trigger a specific initial route at this point, </span>
<span class="c1">// such as `.trigger(SecondRoute.initial, on: secondCoordinator)`</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>We suggest to not use initial routes in the initializers of sibling coordinators, but instead using the transition option in the <code>FirstCoordinator</code> instead. </p>
<p>⚠️ If you perform transitions involving a sibling coordinator directly (e.g. pushing a sibling coordinator without overriding its <code>viewController</code> property), your app will most likely crash.</p>
<h3 id='rxswift-combine-extensions' class='heading'>🚀 RxSwift/Combine extensions</h3>
<p>Reactive programming can be very useful to keep the state of view and model consistent in a MVVM architecture. Instead of relying on the completion handler of the <code>trigger</code> method available in any <code><a href="Protocols/Router.html">Router</a></code>, you can also use our RxSwift-extension. In the example application, we use Actions (from the <a href="https://github.com/RxSwiftCommunity/Action">Action</a> framework) to trigger routes on certain UI events - e.g. to trigger <code>LoginRoute.home</code> in <code>LoginViewModel</code>, when the login button is tapped.</p>
<pre class="highlight swift"><code><span class="kd">class</span> <span class="kt">LoginViewModelImpl</span><span class="p">:</span> <span class="kt">LoginViewModel</span><span class="p">,</span> <span class="kt">LoginViewModelInput</span><span class="p">,</span> <span class="kt">LoginViewModelOutput</span> <span class="p">{</span>
<span class="kd">private</span> <span class="k">let</span> <span class="nv">router</span><span class="p">:</span> <span class="kt">UnownedRouter</span><span class="o"><</span><span class="kt">AppRoute</span><span class="o">></span>
<span class="kd">private</span> <span class="kd">lazy</span> <span class="k">var</span> <span class="nv">loginAction</span> <span class="o">=</span> <span class="kt">CocoaAction</span> <span class="p">{</span> <span class="p">[</span><span class="k">unowned</span> <span class="k">self</span><span class="p">]</span> <span class="k">in</span>
<span class="k">return</span> <span class="k">self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">rx</span><span class="o">.</span><span class="nf">trigger</span><span class="p">(</span><span class="o">.</span><span class="n">home</span><span class="p">)</span>
<span class="p">}</span>
<span class="cm">/* ... */</span>
<span class="p">}</span>
</code></pre>
<p>In addition to the above-mentioned approach, the reactive <code>trigger</code> extension can also be used to sequence different transitions by using the <code>flatMap</code> operator, as can be seen in the following:</p>
<pre class="highlight swift"><code><span class="k">let</span> <span class="nv">doneWithBothTransitions</span> <span class="o">=</span>
<span class="n">router</span><span class="o">.</span><span class="n">rx</span><span class="o">.</span><span class="nf">trigger</span><span class="p">(</span><span class="o">.</span><span class="n">home</span><span class="p">)</span>
<span class="o">.</span><span class="n">flatMap</span> <span class="p">{</span> <span class="p">[</span><span class="k">unowned</span> <span class="n">router</span><span class="p">]</span> <span class="k">in</span> <span class="n">router</span><span class="o">.</span><span class="n">rx</span><span class="o">.</span><span class="nf">trigger</span><span class="p">(</span><span class="o">.</span><span class="n">news</span><span class="p">)</span> <span class="p">}</span>
<span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="kc">true</span> <span class="p">}</span>
<span class="o">.</span><span class="nf">startWith</span><span class="p">(</span><span class="kc">false</span><span class="p">)</span>
</code></pre>
<p>When using <code>XCoordinator</code> with the <code>Combine</code> extensions, you can use <code>router.publishers.trigger</code> instead of <code>router.rx.trigger</code>.</p>
<h2 id='documentation-amp-example-app' class='heading'>📚 Documentation & Example app</h2>
<p>To get more information about XCoordinator, check out the <a href="https://quickbirdstudios.github.io/XCoordinator">documentation</a>.
Additionally, this <a href="https://github.com/quickbirdstudios/XCoordinator">repository</a> serves as an example project using a MVVM architecture with XCoordinator.</p>
<p>For a MVC example app, have a look at <a href="https://github.com/quickbirdstudios/Mobile-HackNight-XCoordinator">a workshop</a> we did with a previous version of XCoordinator.</p>
<h2 id='️-why-coordinators' class='heading'>👨✈️ Why coordinators</h2>
<ul>
<li><strong>Separation of responsibilities</strong> with the coordinator being the only component knowing anything related to the flow of your application.</li>
<li><strong>Reusable Views and ViewModels</strong> because they do not contain any navigation logic.</li>
<li><p><strong>Less coupling between components</strong></p></li>
<li><p><strong>Changeable navigation</strong>: Each coordinator is only responsible for one component and does not need to make assumptions about its parent. It can therefore be placed wherever we want to.</p></li>
</ul>
<blockquote>
<p><a href="http://khanlou.com/2015/01/the-coordinator/">The Coordinator</a> by <strong>Soroush Khanlou</strong></p>
</blockquote>
<h2 id='️-why-xcoordinator' class='heading'>⁉️ Why XCoordinator</h2>
<ul>
<li>Actual <strong>navigation code is already written</strong> and abstracted away.</li>
<li>Clear <strong>separation of concerns</strong>:
<ul>
<li>Coordinator: Coordinates routing of a set of routes.</li>
<li>Route: Describes navigation path.</li>
<li>Transition: Describe transition type and animation to new view.</li>
</ul></li>
<li><strong>Reuse</strong> coordinators, routers and transitions in different combinations.</li>
<li>Full support for <strong>custom transitions/animations</strong>.</li>
<li>Support for <strong>embedding child views</strong> / container views.</li>
<li>Generic <code><a href="Classes/BasicCoordinator.html">BasicCoordinator</a></code> classes suitable for many use cases and therefore <strong>less</strong> need to write your <strong>own coordinators</strong>.</li>
<li>Full <strong>support</strong> for your <strong>own coordinator classes</strong> conforming to our Coordinator protocol
<ul>
<li>You can also start with one of the following types to get a head start: <code><a href="Classes/NavigationCoordinator.html">NavigationCoordinator</a></code>, <code><a href="Classes/ViewCoordinator.html">ViewCoordinator</a></code>, <code><a href="Classes/TabBarCoordinator.html">TabBarCoordinator</a></code> and more.</li>
</ul></li>
<li>Generic AnyRouter type erasure class encapsulates all types of coordinators and routers supporting the same set of routes. Therefore you can <strong>easily replace coordinators</strong>.</li>
<li>Use of enum for routes gives you <strong>autocompletion</strong> and <strong>type safety</strong> to perform only transition to routes supported by the coordinator.</li>
</ul>
<h2 id='components' class='heading'>🔩 Components</h2>
<h3 id='route' class='heading'>🎢 Route</h3>
<p>Describes possible navigation paths within a flow, a collection of closely related scenes.</p>
<h3 id='️-coordinator-router' class='heading'>👨✈️ Coordinator / Router</h3>
<p>An object loading views and creating viewModels based on triggered routes. A Coordinator creates and performs transitions to these scenes based on the data transferred via the route. In contrast to the coordinator, a router can be seen as an abstraction from that concept limited to triggering routes. Often, a Router is used to abstract from a specific coordinator in ViewModels.</p>
<h4 id='when-to-use-which-router-abstraction' class='heading'>When to use which Router abstraction</h4>
<p>You can create different router abstractions using the <code>unownedRouter</code>, <code>weakRouter</code> or <code>strongRouter</code> properties of your <code><a href="Protocols/Coordinator.html">Coordinator</a></code>.
You can decide between the following router abstractions of your coordinator:</p>
<ul>
<li><strong>StrongRouter</strong> holds a strong reference to the original coordinator. You can use this to hold child coordinators or to specify a certain router in the <code>AppDelegate</code>.</li>
<li><strong>WeakRouter</strong> holds a weak reference to the original coordinator. You can use this to hold a coordinator in a viewController or viewModel. It can also be used to keep a reference to a sibling or parent coordinator.</li>
<li><strong>UnownedRouter</strong> holds an unowned reference to the original coordinator. You can use this to hold a coordinator in a viewController or viewModel. It can also be used to keep a reference to a sibling or parent coordinator.</li>
</ul>
<p>If you want to know more about the differences on how references can be held, have a look <a href="https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html">here</a>.</p>
<h3 id='transition' class='heading'>🌗 Transition</h3>
<p>Transitions describe the navigation from one view to another. Transitions are available based on the type of the root view controller in use. Example: Whereas <code><a href="Typealiases.html#/s:12XCoordinator14ViewTransitiona">ViewTransition</a></code> only supports basic transitions that every root view controller supports, <code><a href="Typealiases.html#/s:12XCoordinator20NavigationTransitiona">NavigationTransition</a></code> adds navigation controller specific transitions.</p>
<p>The available transition types include:</p>
<ul>
<li><strong>present</strong> presents a view controller on top of the view hierarchy - use <strong>presentOnRoot</strong> in case you want to present from the root view controller</li>
<li><strong>embed</strong> embeds a view controller into a container view</li>
<li><strong>dismiss</strong> dismisses the top most presented view controller - use <strong>dismissToRoot</strong> to call dismiss on the root view controller</li>
<li><strong>none</strong> does nothing, may be used to ignore routes or for testing purposes</li>
<li><strong>push</strong> pushes a view controller to the navigation stack (only in <code><a href="Typealiases.html#/s:12XCoordinator20NavigationTransitiona">NavigationTransition</a></code>)</li>
<li><strong>pop</strong> pops the top view controller from the navigation stack (only in <code><a href="Typealiases.html#/s:12XCoordinator20NavigationTransitiona">NavigationTransition</a></code>)</li>
<li><strong>popToRoot</strong> pops all the view controllers on the navigation stack except the root view controller (only in <code><a href="Typealiases.html#/s:12XCoordinator20NavigationTransitiona">NavigationTransition</a></code>)</li>
</ul>
<p>XCoordinator additionally supports common transitions for <code>UITabBarController</code>, <code>UISplitViewController</code> and <code>UIPageViewController</code> root view controllers.</p>
<h2 id='installation' class='heading'>🛠 Installation</h2>
<h4 id='cocoapods' class='heading'>CocoaPods</h4>
<p>To integrate XCoordinator into your Xcode project using CocoaPods, add this to your <code>Podfile</code>:</p>
<pre class="highlight ruby"><code><span class="n">pod</span> <span class="s1">'XCoordinator'</span><span class="p">,</span> <span class="s1">'~> 2.0'</span>
</code></pre>
<p>To use the RxSwift extensions, add this to your <code>Podfile</code>:</p>
<pre class="highlight ruby"><code><span class="n">pod</span> <span class="s1">'XCoordinator/RxSwift'</span><span class="p">,</span> <span class="s1">'~> 2.0'</span>
</code></pre>
<p>To use the Combine extensions, add this to your <code>Podfile</code>:</p>
<pre class="highlight ruby"><code><span class="n">pod</span> <span class="s1">'XCoordinator/Combine'</span><span class="p">,</span> <span class="s1">'~> 2.0'</span>
</code></pre>
<h4 id='carthage' class='heading'>Carthage</h4>
<p>To integrate XCoordinator into your Xcode project using Carthage, add this to your <code>Cartfile</code>:</p>
<pre class="highlight plaintext"><code>github "quickbirdstudios/XCoordinator" ~> 2.0
</code></pre>
<p>Then run <code>carthage update</code>.</p>
<p>If this is your first time using Carthage in the project, you’ll need to go through some additional steps as explained <a href="https://github.com/Carthage/Carthage#adding-frameworks-to-an-application">over at Carthage</a>.</p>
<h4 id='swift-package-manager' class='heading'>Swift Package Manager</h4>
<p>See <a href="https://developer.apple.com/videos/play/wwdc2019/408/">this WWDC presentation</a> about more information how to adopt Swift packages in your app.</p>
<p>Specify <code>https://github.com/quickbirdstudios/XCoordinator.git</code> as the <code>XCoordinator</code> package link.
You can then decide between three different frameworks, i.e. <code>XCoordinator</code>, <code>XCoordinatorRx</code> and <code>XCoordinatorCombine</code>.
While <code>XCoordinator</code> contains the main framework, you can choose <code>XCoordinatorRx</code> or <code>XCoordinatorCombine</code> to get <code>RxSwift</code> or <code>Combine</code> extensions as well.</p>
<h4 id='manually' class='heading'>Manually</h4>
<p>If you prefer not to use any of the dependency managers, you can integrate XCoordinator into your project manually, by downloading the source code and placing the files on your project directory. </p>
<h2 id='author' class='heading'>👤 Author</h2>
<p>This framework is created with ❤️ by <a href="https://quickbirdstudios.com">QuickBird Studios</a>.</p>
<p>To get more information on XCoordinator check out <a href="https://quickbirdstudios.com/blog/ios-navigation-library-based-on-the-coordinator-pattern/">our blog post</a>.</p>
<h2 id='️-contributing' class='heading'>❤️ Contributing</h2>
<p>Open an issue if you need help, if you found a bug, or if you want to discuss a feature request. If you feel like having a chat about XCoordinator with the developers and other users, join our <a href="https://join.slack.com/t/xcoordinator/shared_invite/enQtNDg4NDAxNTk1ODQ1LTRhMjY0OTAwNWMyYmQ5ZWI5Mzk3ODU1NGJmMWZlZDY3Y2Q0NTZjOWNkMjgyNmQwYjY4MzZmYTRhN2EzMzczNTM">Slack Workspace</a>.</p>
<p>Open a PR if you want to make changes to XCoordinator.</p>
<h2 id='license' class='heading'>📃 License</h2>
<p>XCoordinator is released under an MIT license. See <a href="https://github.com/quickbirdstudios/XCoordinator/blob/master/LICENSE">License.md</a> for more information.</p>
</div>
</section>
</article>
</div>
<section class="footer">
<p>© 2019 <a class="link" href="https://quickbirdstudios.com" target="_blank" rel="external">Stefan Kofler & Paul Kraft</a>. All rights reserved. (Last updated: 2019-09-18)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external">jazzy ♪♫ v0.11.0</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external">Realm</a> project.</p>
</section>
</body>
</div>
</html>