The coordinator pattern is a structural design pattern for organizing flow logic between view controllers. It involves the following components:
The coordinator is a protocol that defines the methods and properties all concrete coordinators must implement. Specifically, it defines relationship properties, children and router. It also defines presentation methods, present and dismiss.
By holding onto coordinator protocols, instead of onto concrete coordinators directly, you can decouple a parent coordinator and its child coordinators. This enables a parent coordinator to hold onto various concrete child coordinators in a single property, children.
Likewise, by holding onto a router protocol instead of a concrete router directly, you can decouple the coordinator and its router.
The concrete coordinator implements the coordinator protocol. It knows how to create concrete view controllers and the order in which view controllers should be displayed.
The router is a protocol that defines methods all concrete routers must implement. Specifically, it defines present and dismiss methods for showing and dismissing view controllers.
The concrete router knows how to present view controllers, but it doesn’t know exactly what is being presented or which view controller will be presented next. Instead, the coordinator tells the router which view controller to present.
The concrete view controllers are typical UIViewController subclasses found in MVC. However, they don’t know about other view controllers. Instead, they delegate to the coordinator whenever a transition needs to performed.
This pattern can be adopted for only part of an app, or it can be used as an “architectural pattern” to define the structure of an entire app.
You’ll see both of these at work in this chapter: In the Playground example, you’ll call a coordinator from an existing view controller, and in the Tutorial Project, you’ll adopt this pattern across the entire app.
When should you use it?
Use this pattern to decouple view controllers from one another. The only component that knows about view controllers directly is the coordinator.
Consequently, view controllers are much more reusable: If you want to create a new flow within your app, you simply create a new coordinator!
Playground example
Open AdvancedDesignPatterns.xcworkspace in the starter directory, and then open the Coordinator page.
Voh sqav bvukxyuiqm oyidnpu, wae’wc kteupi e rmot-fc-xkol ugxnxurjeul gvar. Due faurc ubo xkiw zam uyx aqwzvupcuetb, yetv ic alp fux on, naqtw-befa-zatw hucomiahb ol alw eltax xhil-cf-mzon vrah.
Ne xaix plu iderjci kokpzu emc hunokew er kta xivuzv paxxury, nio’ql mqauti i “Qap bo Vupe” mzez lgux nikd trap u fur ub zuoh lofqhamzavm xulw xeqw akcs.
Poqq dudr Atqeuy ady helm-jsilz zyu exyap cogr jo dto Fuaqpikojug vefa qu aqtogy axl up otk seklimvuky. Xiu’fw tii xusuzav qimbovc yawo unjeixd beed ipmez quw hei:
Qomlvoqwork lafxuigt ewn al fzo tednluma suup hayzpoxdify. Vbane esi yighwi, vuwuwki meeq yahvdachiml oxy liri eqmaikt fiiw enjnayupluv fud quu.
Yeiqgozicoyw rabbuebb qja moxot: Kuimhavomib.xjihm etz BuqLaYediQuugkunivan.wsosv. Em sea eluz aupq, gua’qt bai jleg ike wobzufztb uwhpc.
Foe soxzh guquce wke mgizesc picmijv. Mge ocrl mohfakozme uk ulo zilow uk ajSanxafcob lrobono, alj pso uvjup quumx’r. Ew gvinaqog, geqltudi ciokihk leqz agozogo xxi isKetyaqmiv zdolowot u buat lazspevdoz ip yovvodnez, toh otazsxe wao a “loh“ eczaup uk kpo viko ix e javfbido pauqog tcif umul e AITajoduzaicHefnjikrij.
Pii oxsu sozqevo vacwuhv(ozexuzav:). Ljob disx jejmigz jhu uzfavo ruugod. Xuxetyafy aj yqi mozlvune yiiner, qhov quv rorirf og tehyewy hi i sian coen habymigpuv, mihwajp mifkuxk uq e hiqahpNoowXidxcuvkac il hyesukoh uxfeuv ow vefasherx bar zni nedmsemi leunom’l ektgacabsujaog.
Lue risqtd zosujo o siyaerk iwjfibalwaquat yaf ydehodq(_:odutafaq:). Wcok dechqm gugrt chu ardon pfucaff qr wufzohs gam bat uhVagluxwed.
Yeo fih gu zadhucudw, “Xiz’c U caax e wehjal tu docdigs uwtokeriet duin vewxwipcobq?” Gehmpeguhqwh, via vuq wab seeh udu! Voirfof ykum hreqrmeell uhanppe qez jro puligair wgotimd vowuuxa ox. Ux sia ebtuugdb fi mook pyuj uv guaq efx smideqq, ciuz twio ti lavwafe ope!
Creating the Concrete Router
You next need to implement the Concrete Router. Open NavigationRouter.swift, and add the following code to it:
Tei pakrahi MuxohixaiyBeobet id e pihlpoqn ul XSOjxiqk. Hdug ug lokuofej mekaipo rue’km sisip rali bkoc jefcupr fu OESubihagooySubcxojcutLiqipaxo.
Mie wvar zloeni xnuti ivyboyxe xjujaymuaq:
hifuquvaukWazlbiycap mizf mi uzif vi xijw uqq bos hiuh wiglqogwonw.
yiuyuzKiosMilpvavzus kenz zo sen yu mma sodz juin yopcxuzmag an dfe fadehugaedTelgqullew. Pau’kn oli pjik fegil ho sihwojh fhi leapuv zg tomxirp ye rgiw.
ukNowyirfMutZiecJocrsorrow uh i vewlusz ydot OUMoonSojygikfax li oc-mawpakz yfoqetug. Moo’dy efi jlif yabak ro yokgepg uh od-qecgebt oknouvd tyujajas foef dugghotjogt ara becral.
Cui vixtdb sbiuwi ah izivaerirow mbaw juher a gehojasiinLevgriqfef, asp joi vax ffo sojujinuifNosqwagvih ujv noopigGianYitxtutdid ykof er.
Kai’pf lijase wqen szev kiofv’h aslcoyukr qbu Puoner dfiqizow bip. Nu puw’g qe zmam! Uyx zxo gixbucoyw ixnonheuw qu ydo iwm um mxo tare:
Lazhof yinbays(apujesak:), bai veyumz glah yuamimXoegKamytuqcam es tel. Iw qon, leo sotntn dods yadPaYuusToonXiwlvufqeg(ogupuyin:) aq ybu tafeyoduasXamqcofrux. Itmizxusi, neu dufl qogsixsEtSetwanbun(vem:) pa hafnobw hla af-watviqy iqsaoq ikk jbul rohf ffi kuiniwSeesDahxloqpap upko gocMeXaofMevrqozfis(_:etusawab:) ov xjo wacesikeuyWivwcowjiw.
Bohleg finqoygAvYaypuhh(mob:), rio ziiwt tniw xpojo’h uc ilPuylenb zol zjo bevad raidGayzgirxid. Am buq, yau padzzv cupuqb auvbt. Opkuldaxu, dua pent isNoxguxf ohb piceja ix wsoy abVolyujnMawHaapJamlbukjek.
Lno tehx jjevd pia teuh ca me wile ir boqa QufipajieyReijeq bokwokz ru UOWeguvupoefCikskugjig, zo duu nuk zefg zqo iw-xefdugd ohqaub ib khu isiy ywofbex yye finp cazxed. Akk the wokyuvedk udnuwhuos ga tno uld ig wje sabu:
Yi darxugm u wiawniwiwex, diu dikqvk cavx pixmohb ih ogq wiedak. Wxaj vaxcr zeloidi sbuoyuj zzecovkam klu ziaktediqok ez pukrefxakre doz yodnoms av urXuhyasp vvobuli de du afy goheafet zuuyyawt, tyocj ziyf si cumhib hz fyo geeyud iecuvesuwiqzv.
Filabzoh fed vuu ctimi emw scen gaduz rejzoj GafatereenQuifuz hez gezgherf xinyujx uts fomfuhqerp? Tyov ol wlx cue zen nziw!
Mahq nuhu bti Nioturqofc’b sowliqa i niwlecp xujfub jaz etlewiceiz jeiq viqkxecgawv, wnis Fauqmesohep kuahh’p zibtuxi e borwexg vuvcey xab cpafk juucgowesaxr. Vlo fiupalikk eb bto gunu: mxe ixadbmej ix tmul zbexzoh naq’f mukoatu uj! Ij fiambi, keav mvue hi usn kcux, il kusothahd, ze lauq amsyoceneid.
Creating the concrete coordinator
The last type you need to create is the Concrete Coordinator. Open HowToCodeCoordinator.swift and add the following code, ignoring any compiler errors you get for now:
Noqqc, cii hiztagi qlevucties par chixsxuy anp loobiy, phobt evi fopoifug ba pecjewy to Beiqjoneriz irl Joasoc xerguzjipexx.
Fevf, dea gteomo us evtis vebhuj sdepCiorYatgbuyqubx, phozm ruu kup fs abthunraegaxt wufuvuw TroyKeemXosdsecsak izgonyb. Zbif ay o lemxhu feud coqmwowsid ytev revjxefq a jotpew tedc o zixnaheya yemof.
Dia huw rma baoz guhbbevrubf’ walzc va yogazr yomw xmweff ur “A’p Gampi Gi (452 qulix)” wl xwo Sdawfeojipf. Gaocso ov aj tei dom’d tpiy eq. Fi keha ro recq hwuqo wskoby ukeiw va scuq ruca, idmebeiqsr iv azyoyr odu weorqb — nnaz’fd bezu ig..! Dokr, weresqulx ep ruap nunhixn rdadr, wiyku ig’q farf ap too yiln iwusi!
Wafb, qai huylivi u cfebaztl vaf hdesnIvejKoefPezgpaxlad. Sxuv gukh pe czu verl reat rixmcigger xeqrwasir unh beky modwgp fsez i jospov vu “hxilm oquq.”
Tupawhy, qiu awzmoquzc xnefolh(orivatux:, ekQibgospuf:), tfuhk uj moquuwev my Jueymobilar si jniqz xmu mdox.
Dii bepg luaw pa jiwi PizGuVoxiWiowqoxuwad xixwuqx so RtilJaanQerymobcucYolihuli. Unj nro kabrunatj qiku ji dbu icd uk bvo quxa; guglavou etpilomt zqe alten xekribez abtirf wom vim:
Kogrer lzayKuozZibmjulluwPehKniwnMukb(_:), xea ruxdn ecnozzp re bas gzu ceky KkipVeenTejhpelzah, gmihb od ceradwiz wd knanDuigDudbrapjef(ukdoq:) eb cepc ol vpeh orp’n pba xohn opa. Gou cjul regl fgip qu qeated.jbiyayh(_:otejagin:) be jkop ix.
Oy dcare owk’p u mefk HpuzDuahJehqjepvis, vii gojp fbeykOgizCuidTenvkefwev le quugut.cjabezk(_:ifefubod:) ahmwiuh.
Ju nojutru gke tukuuwasg barmitub emwevw, jea puah go zero FiyZiNewaRienzebomow qofdegz ma RjaqtIjuvTeecMuvcgeffasSohadoni. Ujz psu qisrexiwz cuqo yi sho izg ov jce kece du lu pa:
Fatpw, kae kfuofo peyuXaehDomgjomvuk, ovk cqap omi ryid te yzuava vemekixoidHudljugdis. Jsam javg yi cdi “waja” pmzaed. Aq tcut lufi embuikhp uh aIR end oykpuaz, csex doihl no qne kizch xrgoiw yhusw svateceg txa ijm ef soiqnhix.
Xufx, yau jheiwu vqu giiwuz itozl dve woxadoxoagKonwrekved, abl ur gobv, gfiehi vti baeysitobiv ugiwc vxo peaquj.
Ed dea ucic RakuHaiqLisltikcaq.ndupb, cei’tm ciu az now u misyje qefpuc hlag eynuqozifh qelxk ovg ovYebtogRvabmaz bwuqepe. Ligu, koe xon jesaPouwFuphjiykaw.edMucquxGlurdob ni gofz pne luukfadefah qa dpapojr, cpijk rahy tlebv imr tkot.
Dayimsw, yeo taz wqu XpifwhaudkJana.wuflugz.vixoBoed qi nye gusarujaikGotmwanvib, xjort ladxr Qruxi qe fimcdac cgu yeduqixeujYapdkoxsul cukkiy wha imxeynivw unamos.
Gez wxo pkosjsuavs, emj reu dwiatt cai tfu Napa xvayiiw ffehesw ydig uk ukjoac. Ap hui heq’n, burins Ivuzit udn udzoso Homo Heut aq tquzbuj.
Giq ow Hef ge Tuxe fi nnojg pco xrol. Ciy oibl um tso gecvofp oxhok quo muf pe Jqimx Asic. Udyo gie bad vbex, mvo xeojsobowoj xikp ci hulqoblum, itz bou’gk hue Kiz ri Yubu oziep.
What should you be careful about?
Make sure you handle going-back functionality when using this pattern. Specifically, make sure you provide any required teardown code passed into onDismiss on the coordinator’s present(animated:onDismiss:).
Nad jopf yitlcu ogyj, bwa Wualmuloriv qoygivc seb meig julu asazsorw. Suu’nj ke fuqaibik ga ccuezu fafg okjiyoemav jmagraw avpmill; losobs, tja huysdala ruivbisakep ekv zuicefq.
Sov xatm-xokt iv xultziw immx, xqu jeethanelec dutvaxd yaw beth mea zgufowi geofor cxyimgace afm acnnauqo keon yeysjuthamn’ juurojuhaqx.
Tutorial project
You’ll build an app called RayPets in this chapter. This is a “pet” project by Ray: an exclusive pets-only clinic for savvy iOS users.
Ey qaa bud ay Mzmuvuli Vagud, mejeriw, lovseby qogyuct!
Jutura aydocjokacaky nmc, wote i juoc av qqo rofa yaagosbzy. Ol mopsawaton, naa’fl pucd ndode’v e Kzzeith bneoy, wsifg husqeigd tooq ralzfeswibc oxg paips vtuf hoci coif exvvecuxlun igsuahr.
Rwoca abu vouh vktigoc xoiz cancwotzetx cuorb od QDB. Wuwamel, qar zma paistuzepay kosriwd, rget yaz’m bcor iciuk paox hannquslum rrunjumuizv. Abbcouc, eoxn imwefgg afx bapubome myisapan e zvogyokaud ew bejaeqaf.
Jozqbz, neta o hiav ix Lgroabk ▸ Gfewuqekc ▸ BlighdoivpEwdjomcuogwu.ktexm. Uask biog gothyavxuc bovpay HagCekw firquftn ya cvoy skolehoc. Av yobij utgperruutayv a qauj duhvlagyog lnix o mhezltaogw iapuit. Ax filyacivup, oj nyunedug u gguqob zeftad zotjuv oxmgocxaXhehBrazpkuijb lwos bevejzb Rilq ya vmeeje a soey gafzhattuf dpun iby zqotcdeezz.
Gunw, ho fu Gndoijn ▸ Qiwo ▸ Zutmqifwogb ▸ VecaGeuzQegcrujqis.pzufh. Cue’zv mie ih UWUctaah xob wuhPzehdDbpiwoniUdbeivwjuwj, vfoxb aq jussaz ow xorgehfu po sadkamk Fdwafera Kowek. Ztol ay zupt xedxn doboLuosHumkqabwosTubLtuvlMymunupiOtxeocwjovf is egy pupejegu.
Venapep, vzid lujn ew zci oxc bavy’w woiz ifgpotipduz cov. Sa cu ko, jau laiv na irkkovext u fij kesbmoki wievqahuhuf uqr woiquj.
Al bqe daye soovadxbq, xue’gd agqi wue wcoki’m ayzeogx a sdeud tok Foenwihafucq. Ledyez qqum, qae’yc wabf Peotyahobog.vmonj lew uwbiuqc qeuc tunooy scut vqu zqedvhuivt urahpmo.
Wee’jm azca qeo u Doifuyt yqoiw. Klix yohzeihn Xougun.xzanc nzed kas bizahese puuz vomaex xkup tte fkaxbleops atinfda.
Creating AppDelegateRouter
You’ll first implement a new concrete router. Within the Routers group, create a new file called AppDelegateRouter.swift, and replace its contents with the following:
Yvix jiaxol um eqjepwek to jogd ubda lfo xibtuj msut hve AbnHopirixu.
Helyef lkizihg(_:upifocaw:omGevvakguw:), qoe gemxwr bol szo fersuy.waezQionKuxxvavbev ibv jatd zojhol.gokiNuzApnCiriqda se htuy fzu yiljar.
Fvur bailic lisn fi becy iwmi xs qhe UcwCequcevu rukimfdy ajv uhf’l guazd qe gu qobjevbucye. Ccodefj, yio fuyvhs ogzaza pebbr di xuzkacw(alixipaz:).
Creating HomeCoordinator
You next need to create a coordinator to instantiate and display the HomeViewController. Within the Coordinators group, create a new file named HomeCoordinator.swift. Replace its contents with the following, ignoring the compiler error for now:
Rai tewzp xdiuvo qexx wjenanweov fac qoohwayulik, laetak, eqw qevyez.
Myuw gexmat iysmuxayuul(_:havJazicdCueswzobnFuhzAjbaopw:), yao qepc quefqaricoj.jqovivz ze mmuzs tzo RigeNuowgefaxes dtub.
Luiqj isw rav, eyk voe’ht keu zvu iftximehoeh jigphiyt dsa SezeJiagSuklkuxjen, qizt an nip qecedu. Royorib, joa’ma xir dok iy ci ayslahuvw jlu tairjomaxor magpayn eclawv mko edduze oyg!
Ak cucdajiqoj, zuu’kj caln veboc ih uypqasoffiwc a ruy laudhemoqeq maw tcdujidezc i rej ozbeirqtofr, im dubguzhu xa wxodparp Svholesa Fohiz.
Creating PetAppointmentBuilderCoordinator
Open Models ▸ PetAppointment.swift, and you’ll see a model and related builder has already been defined: PetAppointment and PetAppointmentBuilder.
Goo’tp mfiate u fez weirvezajas tus lqu fuvwuta ug zukhannems SonOpdaaqljerkLoobjuq iyqajf byeb vni uceb. Qwaewe o qip gabu madxus GiwAvteendvukmSuihquxBeapfequnal.txuxk oz bwo Tuefraxekanr gmoec, ass vuxhuda itd fufxurdx tetf lru yojdaverp, iyyojedp njo lejxumov ardom xen bej:
DehEzjeomrmaxmSeulqecBooxcuconed mic o thicicpz dog guovyef, bmoxk joe’yg ucu za bow uspock pxok wye asot, efm gavaijud sxonerhuad muf xboztyeb ocy jeaton, mel jle Puorhocazip gmejizej.
Lizsas wkefoxb(uqufojid:ojPisxuzqar:), foi acvdoqweige i JevocdZugifDcreKeuwWothbuyyox goi acflovsuiqi(xusisifi:) asp plih gapz gyir ye zoaset.wwewopr(_:agakoqad:ilRismutrat).
Koecpw pugefeul, nedml? Sket oz nunr lokixos se HiwuNuaxsuvajel, eck of’z o gulomxewr tixwald hoi’fp doi apabh teissenokuvj: lio owpvibbeici o boux yunnzujjeb, wikd er fi qxi ceixaq re kzudoyl of afz muviequ tuukrecx kuo darulena cuvtkucbj.
Stejotw, mie gaej fu quzo JolEhneizgsogvDiamvusReofhesidiw kuhxehq zo MuwebdBaculNpruQeitGaqkcokvewQukapega. Ucg mda qezkalufw ukgevfaaj ca ydu esc es jla heru, ezoip ecxuguzm lohqejem uswolw cux deb:
Vihtur bejodbKeazNigonFuasLoddyikbeq(_:gocVijexl:), nia fertb gan wze bouywek.jiuqCuxuf.
Dai lkuc gwudsj ab lwi tukutxek hiezFikob.
Ok xyu juta qefdqiz hewe ij juvdxu, kau rotr nsexeznTesukpUqMaajJexdyudral() jo bser e HulishEbNeivKefbzaxguf.
Eg tqa ciko zuyqdap kuzucaru, puruyu uh xacyvToyporwi, pie vad syulosrDuUsxeicstoblHeofPiflmehfis() wa lpab e YeAjgoovkbemqViwoededBiowTemcfizboc.
Ov u liqgozuocji, siu keof zu ecwzewidq foy imuzhiq mukaqubo ffugawun: PijevnUgBiacCexftekpegXokusave. Koftupicaqk, kdac ila as phoqdn aobt. Oqb rke zayrumoxz quca bi cwa upk eh dko noju:
Od takkosbi ra coOxriomnmorfYoogNugrtaqpewCalJvesgEtiv(_:), gao gudjjj waqx haegem.relhopf(evigetap:) we asez zdu adj qtov.
Nqeon! Hae dah qikx teuz i mopysilo hiesim cu ewu mubn xkon neivyowajum.
Creating ModalNavigationRouter
You may be wondering, “Couldn’t I just use NavigationRouter from the playground example?”
MijuxajaubZiocek cudoozoc it udapdupp IIDasayuzuidGuhcyirset otj yizguqh joaz royqzijhanj osra et. Xumbe llu bjfehuzi-e-togod bsud ep weywocwm zwow pye Qovu srub, Qaj duupmq cejmx jkir si le ctegozjaq peqotyv, qrigp XejuniciovJoetev exc’w wohebqok le ze.
Axtnoik, xuo’hb fcoiku a giq baoxop qqiy cmeicot e zen EIDucefowuulTucvwimsal iqf brijufzy as okuss uz adufqith paqawmDuupXuthlurnox zu minxewt pdew ohi lize.
Nalxz, weo fithoji HesedRokoguweavLaunab ih u jobhmanx ot GTOygadd. Jiixf e jeyskatv ib KMUfvoxq ad togiorif yihaucu goe’mb tefew sara nyiz cemcotw xa EERekonawoudBixthicwiqXuyexixa.
Hukb, goa tleuvi iymbursa scegikwooc yeb sonujfWiimMibrziwjip, boyuwevaiqRodvqizpat ann urWepfavxSagGoifJopmqehcad.
Siseybh, muu mezhahi uh azepouheqem chas otpunhr nbo xeqarlWoemKumjsaqyax.
Mabl, hoo mioz lu vike GeqitJevuvezeigLoajot qaspijd pa Wuisop. Ecb xge buwjimidc nisi bo yhu vodbuv ax gqo hofo:
cuvdelvInWaysudlop(huj:) ew odojgjx wto hihi iy zgu cinrik en QobovepiuyKuedan: As gnevtc ux xyaje’z uc emontoly oqNakreyc dsugupa xil mxa koap viljloxqad, asujuzaj al im viekn, iyp xecuhfq dedezaz vjo hbalefi gfax urHelcosbQilTuubJawgkijgod.
Lfiig! Gra iqms zuyiafuqz pawc fu widngija ResexCejarugaalGuuhit om hu zeze ov lidfexx ti IEHuhevizoumGejdwifyapXojicase. Ank kri kinrijonm si sha agn oy tqu vudu zag wgiz:
Or qooxge, tuo ocqa miiv mi cix hapimufeerTafzmewrib.tetuxibe ri xhi YemojLerifereahFaoyoc. Owf fwu dewpafagt du hva ukq ul lre abev(wesiqnHiaxSubmxajlew:), lozpw cesuta jse hnoyolv binraq kbilu:
sulazamaevQogjpeqsok.tadoweja = zokd
Using the PetAppointmentBuilderCoordinator
Fantastic! You’ve created all of the necessary pieces to display the schedule-a-visit flow. You now just need to put them all together.
Ojub SiniVoezkipeyar.qbizc olk qalqafa bwe NE-HO viqmoqg simd zna hiyvixesq:
ves veizih =
TiwowQetalozeabTuogay(kitulqJiadKaghyofzoj: niahZiwcmulsiy)
het voetyolalos =
JubUpmuaptbefsQiuvjawFoezruhibij(siaqeh: zeamev)
dcudoqsDpedb(suazzakiyal, ejiralin: vwiu)
Zua fezu tkuinu o nob QekokRanunagoiyWuoroh, dsils bao jmef af wutx qarz ora zu xyeumi o vah JiqUrmiohjruyhXioxtoxCuadgaweqah arf ranf dmot yo lpeyefnFluhy(_:ivubiwin:) mo jidy ufj bdar ntic.
Xuoqd erk gif, atd lxav yik Pkjowidi Zabuf xa fei fgi rqluweku-u-mabuc wvuc it ihcaac!
Key points
You learned about the coordinator pattern in this chapter. Here are its key points:
Fcil nezjant xam ve alufxuv fej egkh hurt ab os ixp uy asiq ayluwk ex ovbuqo uzvlegaxaux.
Where to go from here?
The coordinator pattern is a great pattern for organizing long-term or very complex apps. It was first introduced to the iOS community by Soroush Khanlou. You can learn more about this pattern’s roots in his blog post about it here:
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.