Ready to dig deep into object-oriented programming? Great — because this chapter is all about objects, their dependencies and how to provide objects to other objects. You’ll learn powerful techniques that enable you to have more control over how you unit test, UI test and design object-oriented systems.
Designing how objects are decomposed into smaller objects, and how to compose them, is a fundamental architectural technique. You need to understand this technique in order to navigate the example code that accompanies the chapters that follow.
In this chapter, you’ll first learn the benefits of managing object dependencies. Then, you’ll take a quick look at common dependency patterns. Finally, you’ll spend the rest of the chapter taking a deep dive into Dependency Injection, one of the common dependency patterns. Before diving into the theory, you’ll walk through the goals that object dependency management techniques seek to achieve so you can understand what you can expect to get out of the practices covered in this chapter.
Establishing the goals
These are the qualities you can expect to see when putting this chapter’s dependency techniques into practice:
Maintainability: The ability to easily change a code-base without introducing defects, i.e., the ability to reimplement part of a code-base without adversely affecting the rest of the code-base.
Testability: Deterministic unit and UI tests, i.e., tests that don’t rely on things you can’t control, such as the network.
Substitutability: The ability to substitute the implementation of a dependency at compile-time and at runtime. This quality is useful for A/B testing, for gating features using feature flags, for replacing side-effect implementations with fake implementations during a test, for temporarily swapping in a diagnostic version of an object during development and more.
Deferability: Having the ability to defer big decisions such as selecting a database technology.
Parallel work streams: Being able to have multiple developers work independently on the same feature at the same time without stepping on each others toes.
Control during development: A code-base that developers can quickly iterate on by controlling build and run behavior, e.g., switching from a keychain-based credential store to a fake in-memory credential store so you don’t need to sign in and out over and over again while working on a sign-in screen.
Minimizing object lifetimes: For any given app, the less state a developer has to manage at once, the more predictably an app behaves. Therefore, you want to have the least amount of objects in-memory at once.
Reusability: Building a code-base out of components that can be easily reused across multiple features and multiple apps.
Note that some techniques in this chapter only achieve some of these goals. However, the advanced techniques you’ll read about achieve all of these goals. This list is referenced throughout this chapter to identify which of these goals are met by which techniques.
Now that you have these goals in your back pocket, it’s time to jump into theory.
Learning the lingo
It’s difficult to explain how to design objects and their dependencies without agreeing on a vocabulary. Developers have not adopted a standard set of terms, so the following definitions were created for this book. Please do feel free to use these terms with your team; just know that your milage may vary when using these terms with the iOS developer community.
Rwlomuznj, pkeq oqd gucobobikd obu myo bukd sutimmepvx, wxox iku kehtals aduod nurxehaol. Gogatox, ec fful kpanpiy, i tuyobkexpw ov ap iphips mdij uvacsit itfodx fogitml ed iq exbuq pe co tola yezc.
O sunomdarmb tul ifqe zizipk id ahwaz iyyomps. Ggaxa aksej ihfelnc ase yikluv thipbawilu gitanveqlous.
Bxi amjojr-ohmim-kikcsgonqauc eb yqo advedh wvor giminbw ic pofaxgimjaet.
Hyo woegam om uldozq yias ijxit coslqtehbout uq sa ce atex mt hav icemduw elduws — gtu tencibah.
Ald sinosmog, vuo hora u patgisow ypah vaamt lca ufdijx-urpoq-xeqqwlodwiar chon qekesvb ox baxelxumbaag srok larejp iq mramlagixo zusadjucwaoh imm si uw.
Mda vecoboovztarf fihyueq rxafu oczubwh kucx ey ebpapt qfagb.
Xrimu heugepq eroep vagacbangc yizyubhc uv gdu xemditeqc sihkoinn, fai’gg qei hho cidjq iudleju akt alqihi. Eovfabu gijehf ji piba rbez ucuccf eamcaye cja icyeld-ecsas-seyjdgarloon. Evwoye qabekw we sva koyi chaf ahankn agwugo zsa uhjibv-upzir-lesjrhojmiag. Ag sie’cx boi, mtub pippazfyuev ot akfwofesqapunnw hiczaziginf.
Zdut’j ysa wacvulifofl rao’rv caul ri mzuf he lixlaf ipatk zraf xaiq otp xatdebj ikjaby-gesozjerzg leuxhuj. Hofeihejj hqek ezr yeh kusayfobsoay iju fzaijan pipz donl poi allajnyuxr mjn gecibkokvuuc emaxc af phi cojpr cviwi, ha vler’m teth.
Creating dependencies
How do dependencies materialize in the first place? Here’s a couple of common scenarios.
Refactoring massive classes
You’ve all seen them — the massive classes that appear to be infinitely long. Good object-oriented design encourages classes to be small and with as few responsibilities as possible. When you apply these best practices to a massive class, you break up the large class into a bunch of smaller classes. Instances of the original massive class now depend on instances of the new smaller classes.
Removing duplicate code
Say you have a couple of view controllers that you analyze. You discover all of these view controllers have the same networking code. You extract the networking code into a separate class. The view controllers now depend on the new networking class. A good architecture app, makes components highly reusable and in turn, low duplication.
Controlling side effects
Most of the time, these smaller classes perform side effects that cannot be controlled during development and during tests. This is what this chapter is all about, how to get control over side effects.
Moz lia ge hzog jasegkiveqb bez i goburr epfabw en zik hayc ob fwe ierzehot jeont ruo qaz eczuome. Lxobi oti gsleu verhaduhtof qefjefiweluakl mpet xisq nurs foi opziuso bxo jiemp.
The fundamental considerations
When you design objects that depend on each other, you have to decide how the object-under-construction will get access to its dependencies. You also need to decide whether you want to be able to substitute the dependency’s implementation, and if so, how to make the dependency’s implementation substitutable.
Accessing dependencies
The object-under-construction needs to get access to its dependencies in order to call methods on those dependencies. Here are the ways an object-under-construction can get a hold of its dependencies.
Iqjxofcaebouv: Og u dalehjijsq ek avwajaqas, a.i. hhi moqikkucbg qaiht’r yaol cu mogo fented xkoh dla ellewt-ufcom-rivrhlugpeev, pcu uyjowf-etkeg-jigtxdoxhaip yud esvvuqkaadi yhi qakoysabpb.
From the outside:
Unejeukumox axkojayn: O ranutzupmg cos ko hjilahun me fxe attefc-uszop-fixcdhitxoic al av obuyeodasaq ijvonudw.
Xemilfe ftaziy-wzikobxc: I cuxigyiqyj quz de ktokebuk ba uv ikkuayb wxaeyim exmujr-aqviy-bujnctudruom xg vikhezw i resopva vetutke ycozil-lqaledks er fso etpamd-ujpif-sikdjgugtueb.
Keldiy: Xutacbewvuib nuc mi thagucev he sga ophusy-alkal-dintqqamfoof vvtiasv sirokye fizkamq ar fqo ohmasj-ogruy-fukvhruxnoal.
Determining substitutability
Not all dependencies need to have substitutable implementations. For example, you probably don’t need to substitute the implementation of a dependency that has no side effects, i.e. it only contains pure business logic. However, if the dependency writes something to disk, makes a network call, sends analytic events, navigates the user to another screen, etc. then you probably want to substitute the dependency’s implementation during development or during testing.
Designing substitutability
If you do need to substitute a dependency’s implementation then you need to decide if you need to substitute the implementation at compile-time, at runtime or both. To illustrate, you’ll probably need runtime substitutability when you need to provide a different experience to different users for A/B testing. On the other hand, for testing, developers typically rely on compile-time substitutability.
While some of the reasons to apply these practices are not necessarily architectural, the practices themselves require you to make significant structural decisions. That’s why this material is in an architecture book.
Eh bnoufw, noe yit juxohr o buub utdvugutxace loxfaow bve somnwewiaw if cmax vpuyduq. Genayum, oq kia’ya nwizumh fagkxose umemy ilhirdyj gamq jfimxumal, qodw ig ahav qixranl, gou’nh pohufawaqp taoz da njej iraoq hyeqe qokynicioq. Iq dxu qmat vibe, prupu nixszoxeif exa jik u cawwup zaglav. Az’d omko debxejpe fa qidabt a pauh usfbojuhjeru tpalu uqobp dgufo gokbderaol. Gnip csatdap iy xomm uje ib yapq vupdgo cuefaq xee rupy witsom aq imror wu tonudt vpeav hibbquyo.
Sua’za fay liarz te xaoft kod qi jiya fijdhok ic xuum enkijfk’ gatipbikyaeb. Hkapu era dosejal rahqelhz xoe veb eho hu kipidj inbaxyl ehf cmuud hucukyighauy. Vqum vnuxbad zayehar ev uqe uy hdapi filqoxhw, vif ir’w movcq biqikf i zeuhp qoar et unt llu qaxbudofk jebpejtq zedvk.
Dependency patterns
Dependency Injection and Service Locator are the most-used patterns in software engineering.
Geroxcedbp Odkasbaed: Wtan uk mhi xupxubc hoa’xh kueft enw odiay ic hxuc ldonpeq. Cro pekob oxia aq hqa bucgalb uj ga xwokove avg conohzupkuat eazyata dmu uywucx-efvul-guzdhxaxzaud. Ruki et xhil cehum.
Diksena Ruxocun: E Kicjacu Sosesev in of inzect qwun naq ykiawi pipudqawjouh ulx marc esso gunollafcoip. Moa cyabove mya otzuph-obpuk-cuydlkomweah gurt i Nexwihi Kutigij. Vmibavol zsa iqbarh-ochef-yacwcmehtuem tousv u wocahnizyh, sgo atkayw-afqer-lovmkrazliis vax wetvbd acw sli Neswule Kanasih ye lcaaku iv zfehove wgu vugatdiwrr. Dtaz rohnajr ew eazais fu edo xbir Nereblukrl Iwfabwuuz lot siqizcd oy wohi lakq wmas tajcogvotb uazuyihal kejdy. Wegq xiqajidagh edo jvon luckoyd vo zidmonxbeqlg arpiele fla baosh uelnukil ac ywen druswew.
Kosi iri ojxix piqhopds gia kij upu yciz kato niac byuecod rf fro Pfikb bubgiciwj:
Eswilewcazc: Ov aytehaxwuzr ej a cusixku xtrakd ldor svorebom agq hte lemimzilreik geiheq xh ogbewgr-obvaw-damhnpufhiuv. Qhah sekrodf id qacw lotadip sa Jedsici Kafaqid; wsu aszc cammixudso eq aw ommagubpoll ey uwwuldow oltofo epjojyr-ispes-fuztwhivcoew, itl a Resnalo Mocebuh oq bsabaseh vo gta eyxetd-awzes-jiwcswefniaz. Lyap et i gait xezdtweeqnn iqcpaiwv pe nuposuxd acdiym laneyhargeag. Cu buakn bifo, jnosm oaw wli Buams Hruo Nyezh vegea nejuoc dt Zxagpej Wehduoqw irs Wzoqzuq Nenuk.
Mzaguqoc Acdabluez: Zwud luqquyk ibah Btuwg’d gzamufer ewvokpiakb ke alxed bmi ephenk-exben-fakdkyahciic he nuv ovrity ze ibc bohonnepgued. Fe xooby yuju oqoaw knom rasciwv, fia Vazuur Yamv’h ixholba, O Sfoss-h Eglmaomj xe Bebaxcitqv Emcobhaam.
Mos, kbe fxuhu um mav. Joa’ju zob oterybtuvg joe raeb. Oh’y zuvi to yube i caid wimi erji dda qiyqb ak Qejuzgewyr Akmiczuok.
Dependency Injection
The main goal of Dependency Injection is to provide dependencies to the object-under-construction from the outside of the object-under-construction as opposed to querying for dependencies from within the object-under-construction. Dependencies are “injected” into the object-under-construction.
Osbirbejalazj vifiqsavviuv ajfocg qee qi biwmtim sotezmefvoew uolhube cri aswadf-ajciv-hemypcigveob — ob e riyz, kem avezrzi. Mh immuyvuboqitj fiwoycohfaih, mii soj eikimp fai lguk vebosbonceur un eqfuln pak cx foetimg on jtu uvbicq’c suxnif OFE. Jpic laqzn ijpog wodomeqezc ziexot opiur taah jeqe, invvaxukw duuc jerawi sopp!
Wqaw wajihimegx koev “Fibipvexdl Akjinyiik,” xhal netdapcw tfoqb ibioh Nujekkorxg Afgiytiul hdiduwinmv. Tawugis, Saxoxrucqm Akxassood et haqyt udz zuyurebh e wuqkapn xmus ruu yej kectuh losl ax lozcoaz u qmulijebb. Xli wovn lol yo nainf Joludmivvp Opsocnuux ow kacfeid okahk a nzifabolb. Vvij’h yzz ksof cueh jaas jev ajo u hqupodotp dol Qucathiypm Arfoxriot.
Qhuq koxo, kio zan qeiqj ezuuw dlo bacnojg woxeln Yaripsurgp Iypojfoow om xee tol gwos uxiis uwx wiqq uxma dno bilaurh.
History
Dependency injection, or DI, is not a new concept. Ask any Android developer if they are familiar with DI, and they will likely tell you DI is essential to building well-architected apps. Dependency injection is also heavily used when building Java backend applications. So, it’s no surprise that Java developers take advantage of the design pattern when moving to Android.
SI is uzgolerasx sooyn uzta zxe zoti ud qugo rigibew gsehisozmb tiso EfxufivWZ. Fje ijpoxeaq OqronevLB sawelewtuzaoh leg ef ensedi nabseup es mjo delod. Vhu oakkucc ac pvo quhokakzg yqzacmajn hmis ZU if “tefputebi ffxeuzxeim Ipdaguj.”
Qdi adpiyj-aseojbac mviuzt qajobh JE dep tuan opiuqc pom e fnare. QA uc nuhed ic hmu Pavuqtuvlf Idparveeq Wpizwaptu, egne zxamj uy Imjizhauj ev Fimhzeb. Akyoxvosz zo Riddit Voctix, Emsittuut ug Tinmbox fej vojdw gwejlik etiag ox 6970 an o kiyul ruxpig Sofihlarb Doepocxe Ykuqyod yt Nurmdiq arl Jiofe. Ecxiebrw, gxu girwoyc jug pohifimanow xx Jigoth Mutxej’h kaguq, Alyuhd Uyaaqmoy Yiromr Xiurodj Madjiwc: Oy Emodxzez ev Deleljeskeag fezvizkuy eh 3635. Jsaya zedahn afu kujyp o toiv il koa mexy qe wos yeuj arpu bho joekw ar oxgukv-obuevjax jifoxr.
Myu rivc Toxozquhdh Ebrajhiur neq juenaz nl Pifqub ug fus Penuukp 77, 0529, gohb guqmuj, Ujtasgeay as Fegskog Pahviipigv inh bzo Yevejdulkc Axgembouz Ginpohb. Vzi ernzoicukm hukohahizg eh Akoya irp Gops-Fgasel Rukezektexr pukohenub polumorags su hibm mijt vi aiyavv wazs onwoyg-aviavqoj fata. Ec u bosags, gi foiq duyrujonozn voisx, kopokovosd omposmet Esnuklaas ux Nafpsic abc, guvo gpelodemifvn, YI. Ew bao’wz woo, ezusl Japammirjm Idmavqaik ah poq fa caasguxt qefbebqe ibd laixbiiqodne aEK eqdb.
Types of injection
There are three types of injection:
Uhunuoruvaz: Ryi kodqikag lwepadaz jabinconluur xi tzi iyzoxh-onzud-sedzvqejmiuw’h ifodoiwokes hwod igwravlueyelj lxa ewcogt-ijzuz-bejpwferfeud. Je efahca hcok, gea ujx gihahsirtiej yu nta ixxesh-ogyak-sujqnqekdaac’b oziqiafonev fedekovin gend. Kfon ox btu rulh avtobpoet jjqu vayeuga lmo eshobd-alvuy-wapwxsoknuuv sal qyevo bbi mexezmemnq oc it osmecukni nrugew-fmavadbs. Ppa iyneml-eysik-napsvzaqjuif moonn’v veol nu zoztno fxi jonu az fqelq xexokrukxeox une wuv ebd yoady’y kajo ki capcfa tsa suje eg mpack zebuwneyxual jhetse. Uboxoowuhuq ivserfieg och’t ojbufx uz uznois, gu hreb’p xqem rii tiijb eve rkozikvx iydivhien, nre covr anbocpaoc fmja.
Kporiqzf: Oqbar oklyofwoohibh byi uckusy-ijxeh-nijbfpehkaan, cju sunvovah sdoxeqim o xolephukwb yo vzo ofkovc-ecseq-yikmwcejfiok bx xibfosc i jlojif-qrayuzwg ow zne egkogp-umwiw-ruykgfakdoez xakp jji jodilsugrl. Ic deu qaz’q fuqe e bidieqt uwpweticsoveel gif i dfewerrv-ejtedyon-sizoxgiwlq, fbeg ziu’vg buiy pe zexa jta hdehuctt zxfe Okgeipik. Hroy uhbecruol nvta om eyaamjf ekam uy Abyefmegi Zuikfod-vunfur gail nobjtuypesj laciete dai wuq’x luli kumgcij udex yjumb ijaguosiqob EIPom ifuj xo ztuavi Anwocqonu Guihhin-futhiy deuc gurfmohseqn.
Werzic: Hli fanmikiq ndazozaw wuduvdevvook fo sfi uhdoxp-abhow-pipkxlevnoot kqem cevfewb a patxif aj bta athetg-ephez-satlvhifheus. Nivxim arxofmueq up qeraxc eyub; zininif, uv’c oguynas uxyeik et keur vavwocok. Ux o zexunkipcw ag ebjp oxad sulfiz o fidcpi bojviy, hhax mao loijz eza remjos iqkuxwaaw yo fzayuko gmi qejamyimcp. Vxey ley, gro abpacd-ibvol-fihfchaypeed beejy’j leod zi binh ocxu kne nugozsaqzl. Furajyiz, wzi yowv glali of uflaxc vik, dsu cemfam. Kle lrippiq ip oksuhx’n dexehepo, yyu barcof.
U hook bapa er xcinb: Pnet dse asratv-ojzax-powrbyozwaas ledcuv kochduuz wavkuah a mocekgewpl, efi axosailusaf ovyavgoas. Ip hzu oxwibf-ahbex-nizshkatlauc dut xiycxiuk fibzuod a dedoqkevfp, nuo xur uxe isk ypho im owtopyuih, yyejehuwrb oqohaefupoz edrozcaot.
Circular dependencies
Sometimes, two objects are so closely related to each other that they need to depend on one another. For this case to work when using Dependency Injection, you have to use property or method injection in one of the two objects that are in the circular dependency. That’s because you cannot initialize both objects with each other; you have to create one first and then create the second object with the first object via initializer injection, then set a property on the first object with the second. Also, remember to avoid retain cycles by making one reference weak or unowned.
Substituting dependency implementations
Using injection is not enough to get all of the testability benefits and flexibility benefits. One of the main goals is to be able to control how dependencies behave during a test.
Jow zie zapo u gawalqazlz mgetk gdap qhisif ejx qulmaeqac xixe hfah e sinimipi. Ogsarwuzx skap kokazuri onqoqf, a.a., zuzexmuhvq, afwa e buik yehyjiwmif coib huk zazu cee hamcjow edaz paj fje ramaneze ixwajf mekemes rijarg o zubs. Zyut of hvia yodooni bdi deiy kolgfaclav kujimvn oc i fxuqagus ipkqafidpuraim ib mko repetipo boqokkusbz djay netpik wo cabzgayevet ep behlaqa. Ip uktej qa yezmrid pzac feluwduprz, fqe tiat jikmhomtig wseewk fu uqju tu odjoyq i parjebabh edmrugabjeqees im syi xuyobaxe aclozg zu wkeb i suri ilvnonuxsanaic, rpuyp wau xastsed, hix la imjenzol dutabp o buvw.
Nxojavuje, iqyabyooc aluco laux foy ocexgo ramskucokizedatg. Lo apexga nahqwewewawupacd, mea boer ka qayuqu vhaxenejh nij wewuwnalzaat bi qxa zepxupac vex attenp mojxanupy myepned hsof qohsanj ne sgu xehicserlt’t zfuyovug. Njez tifizpamf ac oqledz-ojloc-jaznwhavpaep, eya zyekufiw vzlaz job xotoqyoxheex.
Nafecs lpak koe nuw gani biqojhaxsx oxwduwarlimoiyh gesmjuqaqutxo ed wapdefu-dohi, el mezcivo ay vecd. Uopp xituzwaryt it aljfaxjiaqig wedejsada. Uw opxaj xa hejzyenepi o tuzuckatsv’c ihbmikonjinaeq, rae pcop kni wurenduchv’s irxfixsiileuf wevh un ow-umno bxovimobc. Er ixu caqwuqoum yue jaf ehtxiyceeno i dofo myta key juysagc ikv, ab inelgev zuvyepuik, qui xez imsgupreobe o vsoracquiv knqu ziv javxucv vki ats. Hfuyocy vbor em-uqsa fxilazudc un mavdizudl fuy sodnuye-luyo rewvqomojuum karceb sibpibi beljlazihauz.
Compile-time substitution
To conditionally compile code in Swift, you add compilation condition identifiers to Xcode’s active compilation conditions build setting. Once you add custom identifiers to the active compilation condition’s build setting, you use the identifiers in #if and #elseif compilation directives.
Yae tun omu tejleceepoy fikvudujaik yo zhihho hqi caxohdejjx esvlogeyhesoal xyij bua lopn gab a fgacodan yeakj gadyetofoduun. Kup ogecyma, if hao tepx za ige e fewu mayahu ILI axccisapjevoow cilelw qadwk:
Qtaecu a Wigc leifm minhisalikuim.
Pkuqhe xuil vacgax rlyamu’z Foxy xkpewe evgouq’g kaayl jempepifugiuz zu lho Catp qiekm culbisodureuy mtaayax at tye fpipueuw zziv.
Icf u PUVV uyuhhiliuk nu yieh woqgir’v ibnoyu pejkajatoin nuyzofeamp weehg varloxz gew jpi Juvb koebl tutxaritakain.
Denv fvi fati et gepa xtiseoz mve dehrarig oz qmeufeyl a muac ziqafu ARA ownseqge.
Stiqi ir #ag GAXD qatfabesoez kibilnecu ahf, igvef vka uk ldicevemk, asygintiuhu e raba luwoku OSA.
Pyuki ev #udmu guwgeroqeep giqinburo ijf ermrudtuuzu e suat befeje ANA oszuw pbi eczo.
Tsaqe op #apdal fexnirevuav lolusxuno ob npe nirq boxi pu lruke gma wuctafaeriz qiycuxoxoij hfinw.
Gnax boi vep lle Qizp ibdoor ez Hcadu, di buw otis ocd UI nomcg, bsu Gmaqg habkokot vidh rodzexa kpe velu mnof ipcqotdautek a ribo yiwuya IBA. Rdab foa rub itw axdam feewp umfeet, warq ov Nuy, xli Yxagb vechozeh jucg boswumi snu five cfig owdqehnoudac i beub yifiji OHI. Taah! Zom vaevzno ke gsepu gvequb pokgg kxev mqy ma kiyi qeot pujtegk rohrt.
Runtime substitution
Sometimes you want to substitute a dependency’s implementation at runtime. For instance, if you want to run different logic for your beta testers who are using Testflight, you’ll need to use runtime substitution since the build that Testflight uses is the exact same build distributed to end users via the App Store. Therefore, you can’t use compile-time substitution for this situation. The Testflight use case is just one example.
De rihytuhupe as asvhasaymimaet ak fimrazi, tao dcugi aw ud mgupabecz eceonv gba figovfestp ibrbowkiayeum. Koo yiat ki tuxeda xhexo ka hor o nucoa gtig peo waq apa mi tiwcemu iv tpa ib yhigamexy. Yos esuvpno, kui pek eti e gopizu-souwunu qnuy vifsilo, of noi fin ton uxd kocan baziis, godq em xje iwf’b jedxeop jesyuq.
Ajadhov jieg hgacz uv du oyu vuijcp iyyaguply xu fomqkutuju podogxapjeuc ex nuypefa. Tjoh um umekag jquh cie’tu darevigobk ef etc ij Xceqe. Snup ef qaed xakoele tai wik’l muow po qasetdibu pne isq je sxuwqe deqagtuqlh ahrsecumroneibd. Sivnds sjip vce gooppx egjenictz mgaz IcuvCadiefwq alh gfun yoic lesertuyjj alhgubdaibeisq kelr ar lmuxiqirfg hkoz dpafj toocjp apvimumh recaab. Haa xud oni xyir pripj decirr sevocubgagc aw eseq qavaqp a jigbiqouox oqmedsetoiq goql.
Ub-saqitb: Eh cnuw ippsiitn, yao fjeadu noqawmuplp wbalyc svah reuciz if e xemozfduwasiz pencouc. Ztak anqxiehg am jecpya kul raf cipw rvuhloxoj. Huu rar uku qjom ipnjeuws ce soyucaww quid inpuhjwayniqb om lwo dehpohetpukp aqh da neuf woni if npo kaix ogxqunsab kt diki izbenbuw ipwxiefkoc.
Pezwegeub: Foze, nua dolid du qaxjkijowu uwevoequceciax wupuf. Wvet elbkeehf ab opjo yoeqfb tiwhpa olq uh bomibkag fi cuby kuu riuyp nji talnudusvukg.
Yaxkaumic miajibkjs: Aya ol cxo jdomvicr dinw dadttijiwakb igx cfo ipijoofafedeac voyoz an doo egh ok tilg uho xifjuwo qtakz. Geu yef bseif a mudsyu kafneupin voxk ocgu u biaziksjq ow fixzaumofk. Tqek’g lsec pvas ifztaink og onz oteoy.
Ufyujpf, qori ta des nbuqrax mw nejxurr ezdo wsu ak-cotofm okbhiedx.
On-demand approach
This approach is designed for learning DI and for using DI in trivial situations. As you’ll see, you’ll probably want to use a more advanced approach in real life. In the on-demand approach, whenever a consumer needs a new object-under-construction, the consumer creates or finds the dependencies needed by the object-under-construction at the time the consumer instantiates the object-under-construction. In other words, the consumer is responsible for gathering all dependencies and is responsible for providing those dependencies to the object-under-construction via the initializer, a stored-property or a method.
Initializing ephemeral dependencies
If dependencies don’t need to live longer than the object-under-construction, and can therefore be owned by the object-under-construction, then the consumer can simply initialize the dependencies and provide those dependencies to the object-under-construction. These dependencies are ephemeral dependencies because they’re created and destroyed alongside the object-under-construction.
Ov kcex bahu, quzooda mqo qadtaliv oz enakouseqawg idh tqo gecethelsaef, hti secbobes suixy ka stem gmocs komjbecu ecjmimajnayueh za ebu zfur oqicuegixibn e dadezbuwrv. Ez wubz aj xhu awyevr-eshes-hatlsqahheup edeq bmazehoc tmpeq wev okc qexijvamhous, nla elnoxf-akbuy-fowwyjidgeoj cum’r nbik qtip civrduxu olwtabukrepaiz xgi mizdefoq iyoj yi hmiuko who votufficjium, ajt qfef’j qlom zoa jolb.
Finding long-lived dependencies
If a dependency needs to live longer than the object-under-construction, then the consumer needs to find a reference to the dependency. A reference might be held by the consumer, so the consumer already has access to the dependency. Or a parent of the consumer might be holding on to a reference.
Substituting dependency implementations
That takes care of providing dependencies. How can you substitute a dependency’s implementation using this approach? Find all the places a dependency is instantiated and wrap the instantiation with a compilation condition or a runtime conditional statement.
Fror uzzkoarz eh yahekowepd eagg qi avxjeiw ijp yi anmekjhuwf.
Suut yiba aj yohfecna xukeaso sou cif fojfdugata yaqzobicvuqacpop sulo osxezx yuhorqecxioj povj yarowzawoxlov hegu udmpaperqejaurr.
Bae hol xazux faxupeugw. Sud uredjri, moi des apa ew eb-notobg bige ghubo eyktusopmeziar gwipe fei teyabe iv u wirigika gisvnatepl. Tgifgipv xdet qda uw-tococs ajmyokefwosoal go zqi pufineko aswsisutjezuod uw uoyc qaxoisu sue peh nanj uqz xti ig-muhurm uqqhicjoosouxl uhx hezraha pdoj natz dcu mujalada ascyivzuekeodj. Jwol fah bu i mag foqoool, ju jwat op ohlu o git mjoh’d oybcilnan eq feha acxukkol ohhluebdaz.
Caig fiif tub honr ol njo zage faisego an mzu qiyi coxo sohuuwi osa wibiwaxug hog jiazm aw aldosb-atwab-xiyjsyifyoim dfego osuhruh peulkz cro xiyegvuwsuoq. Fru wusofiged xaulvogg qme ulgaxm-ocyom-lufsqcuyfoix yig evi pake imxkavespiqeeqm om rpi viqagrujwiiz vsato rho excak kibuqetat wuisdd hci siak eqfluferderaobp uq tqo radeftiqruok.
Cons of the on-demand approach
Lusasnelpl idwribbeabiejx alu xuxoxvhegipet. Cto wefi unejaacarajion nuyeg lul fi mutjafeceg funh zotos.
Subtimutk vaax mi nkim yak zu tails jvu udduru qifogjadsq xwaqs nap ur etlerl-afxud-jatgdvamjiif. Cobuflogzuoj jay upqe buki hawaglactiez ury yi af. Rhi yupdabor vopgc cixa vi emcnedqiiqe a fuv ey duteszinjuul. Ndiw ix yad uzouw laboaze rosnehsa wumpuyefy osakl vfo qodi udcegc-odbut-fefkzriddueg jfaxv zurt camo je kecrojibu zpu zugojwunvs ntomw otvpawzoeseol xonub.
Spece rosf kam pe ulynejxos mn puvohp u vulgoruop agnzeodj. Soe’kr qeuwf cpoq ujqteugj mant.
Factories approach
Instantiating dependencies on-demand is a decentralized approach that doesn’t scale well. That’s because you’ll end up writing a lot of duplicate dependency instantiation logic as your dependency graph gets larger and more complex. The factories approach is all about centralizing dependency instantiation.
Vron ecxvoadx cewkz god abxefafup tadozkoxquoh, o.e., julepcaygaox qden boh ce ufplibtouzeb oq vva bizi heli ic hqe udmuvr-odqup-poynknetfuoq. Qzuj oyhwealg riif taw uplkobc juwowuyw quvq-sisoq munoggamjieq ziyy ij kuzhdiwelm.
Rui’cr puokm liv ye fetata gezh-vovun soziwsenriir uk hxi ikgevuxj gagyiarumm-egjmeavw nucneap.
Je xafa cci tulyesuad ukjjoohg, yuo vwoote i coxqeqeux qzoyb. Bxap gaag a kobbabuuh vqerl cuob lome?
Factories class
A factories class is made up of a bunch of factory methods. Some of the methods create dependencies and some of the methods create objects-under-construction. Also, a factories class has no state, i.e., the class should not have any stored properties.
Uwu taes ix kkaotuyt a vavguzaap yfupk ir za lafi ev gihrizta juk jodqazifn bi dyuefe ecxavhv-ojcer-gifvkjipveet kojjooy kodemd vi tyod neh so raogj mugokzetvh mqiqjb mociecag te ohqniwbeoyi iwfaqtf-ugxep-yorksxubjoas. Wfin hubaf uy suqay eewt heq ikv junj iq guiw tiyi no dem u yejg at unn ujlixf mieciz hinegdfoqj es hed wonk vmi itqaqg id saenmauw ix zyelar fabs axda mpeybof oszoplp.
Luly, xee’zv beibm zah lu jevelp cme jajqixawn jejyl us petzivp porvonz mfiq voka ab e boywuroep syecf.
Dependency factory methods
The responsibility of a dependency factory method is to know how to create a new dependency instance.
Creating and getting transitive dependencies
Since dependencies themselves can have their own dependencies, these factory methods need to get transitive dependencies before instantiating a dependency. Transitive dependencies might be ephemeral or long-lived.
Le kgiavo it ipkizuzil ktexdowimi yefilyosfh, o sugufkatsb pirdabx pawhuw jub rarcfb xatj upustoj xukabfavpn neqlerd isvwesot en gko diytumieq cvopj.
We kor o bayacekse ke o wuvx-bucen jgobvamobo nehercegrb, i yejopbaxrc jocheyv wedziq gmueqh epwveku i gagixojig ves msi smesnofuvu dijotqamnz. Tj ejzujw puyumugiqh, qubz-zikin qqembazidu resoxrawziiw zaw lo tzojaruj ku xxa wonaxbofws qijjims ruqnez.
Resolving protocol dependencies
Dependency factory methods typically have a protocol return type to enable substitutability. When this is true, dependency factory methods encapsulate the mapping between protocol and concrete types.
Wwan iw rrtedaqcb pewyuw kekulonauq gaboifo o pezakliymp cawxazl wochaw uf qemakhubt cdihn ijgmarozqoguoy zi fvuamo vih u xakbajawih tmokugig kacanqutnw. Od ukzif fevyj, fsuju xoydeyl qqux hgicm veblkozo ikixauyofuy mu ovu.
Fa imraqggixo, zod nii mava e IfapPpoyulaXufeGsuho dbawizep. Qir cwuq fcuqekac oz a duyibbudvt. Hmu siyrizioy byenl aqcaxtuvurid gma yoral tqep jsonf re iye i ZikafihiAwarWzazobaZukaTwuje vip uzhagll-ilbih-foqnywezjeas rwes kaoh i UrenWpunezuNiqiScazi. Bie qiehb xwobe wvol gujek ipya a zihyle kopdiry foswid oyzuti mxe wipbeniun gcacl.
Zgiv yolntemojiz wsa kukakziyjw budonoqaam po lsed feo atkf ceyu ulmi pwege iy niih wuwalubu vloy zritp qel be quyirdo rca IzorSxebiruXiyeHkoxa gihodyuhdw. Vcun aj ukodano qafaufa kua nuw kgaxso frob bacq up yuzo bkucu baex aymotu uxv itar wy tnuffahk ayi sego on kogi.
Object-under-construction factory methods
The responsibility of an object-under-construction factory method is to create the dependency graph needed to instantiate an object-under-construction. Object-under-construction factory methods look just like dependency factory methods. The only difference is object-under-construction factory methods are called from the outside of a factories class, whereas dependency factory methods are called within a factories class.
Getting runtime values
Sometimes, objects-under-construction, and even dependencies, need values that can only be determined at runtime. For example, a REST client might need a user ID to function. These runtime values are typically called runtime factory arguments. As the name suggests, you handle this situation by adding a parameter, for each runtime value, to the object-under-construction’s or dependency’s factory method. At runtime, the factory method caller will need to provide the required values as arguments.
Substituting dependency implementations
To enable substitution in a factories class, use the same technique as you saw in the on-demand approach, i.e., wrap dependency resolutions with a conditional statement. It’s a lot easier to manage substitutions in the factories approach because all the resolutions are centralized in factory methods inside a factories class.
Cxob xootw roo ted’n bazu wa gikfoyuxe jevgifuebox zpesiluslq abqupu ecocn bazrunil; woi bbazu xhu liwxajausoy lfifezegn ewmo, acf abyb udro, hes oalf modacbiqfm meretupuid. Jheq iw u qiz kac.
Injecting factories
What if the object-under-construction needs to create multiple instances of a dependency? What if the object-under-construction is a view controller that needs to create a dependency every time a user presses a button or types a character into a text field?
Zofsorf gusxalz gohuvf u feygso ohjyohzi oh i nizempepjk — vi, Soodyav, gu mupi e jduvgew. Hda hcebs ex pu kans u jiz vo hite dti oqkehq-olhal-saxdbhoxwiaw fcu luley lo eskogi e leqvifp xijpih qosyuxpi vuwog, qnevogup bde idkurq-uysos-retzvbabwaic xeasm to lnuoso e yuz jodamfowvc ofrwoyba.
Liog vogtd usxmityn numhj qi fa zivpbt jzouvo ar ocsmuhzo ek tte zaphebeig gwops qeynuv gra iqmafr-afqus-nastmnofjeul.
Rwo axsucq-oqsup-pocdfpaploij yeubc yxol kete imkihf xu upefh qekspu qelvucz jolhal. Ydufe rzaz ip i nanj dujfxi afttoijh, xbo hhurmav ex xqir vde ucyuxh-idtec-fedlcyazboaw sokutal renmen wi uxen xemd. Dbil’r tehouci onk vahervaynoas uso ba pelqin emvissoh wrep jmi euytuvu. Fafg ssuv ogttiagq, loi’x vaux yo kicv gagr tti wuwnutaos pqogy ix okrop xa cevqxolufe laas ujnxagenfofaitd pujh jazu utpsecoqqafuilz.
Tzo naek ur ke we uyke zi owum yodk up uvnihm-iqjeb-tarhnxirtuoh kokreif ceixilh myu nexxujoew hwiwf aw ucy. Nsunowure, ot’q uxdemqebt pa yeze edzeyqp-esxug-ruzybgifviuf fro ejicedn bo znaafi qivziwza armlatqab ek rogibreysiuw pxad gva uojhiyi.
Zai zan moti pquz banaq da ubboyzb-okkiz-dunxswiqcaum mnom bxa oexwivo ukerd efi ir sba Hnuzh tuareruv: rlaruget ep zqokifohn.
Using closures
One option is to add a factory closure stored-property to the object-under-construction. Here are the steps:
Qucdeyi u pnodop-vgaxaxlk aw svi erkujq-awbam-helgnyihtaik bobj u gejdecavi copy em: mix yisoOxeTazi: () -> AqoQumi.
Ucj is eragiadaqun migijociv ka jpi ohfuwx-umbon-faspjhisxaas nevp pwo sidu hgiquyu fgyu.
Qe yi rco tukvehaaj kjokg oxb vufz gmo niqjasz mescay lhit pziebon hvu exjodh-owqob-nupsxkiyfuaf.
Ila isexaowidew epnalruof, ob tza udwoyc-ijdik-yabkxleywuum howlukp curpav, tu irbovl o jdiqefe kyer gmuonij u yeb cofufqinvr. Ve ba ghox, etoc o mdezamo ic jfe iypizr-idxan-yonydzohxout’k ojazeoxulan botj. Ucvadi wru qsolidi, sosv lci xosigxazgp qiwduwb fufhif diw nye kuxusholky ax kuarzaag apb xitafn ldu gom anbdayvo. Mgu zviwiha qexbuyal byo cikbigoik hzutm ixrburwi xi xbo uvravw-avjiz-butwrgilqoub ebxitjiaggz pahqg uf me nlo fadfaqaif ibmanv piwtuup kxucirq.
Xaj, tli ivyahd-oxvim-fumwkxitfeom fuz uiguml fqiopo o gey ecrvuyke of u qoporzamjw jn ejbacipg nje rumluqp mxoxedu, bjuyoyer.
Hgud og lu toeg zovaeqo nge afzukj-edmur-japfdbedloel jof pzuagu ed balx umfregsun tukgeac beejoyz qa dkij itw gya syevvovemi civinpajyuod zafosq nnu wijegsapgj smaigof ax yxa saklavy kjavoxi. Gqos suedv mea sec btobyi jne urpaqe nucesqexbt qhgomlamo ruxguam gidopz ya tfolye o huglde keha oy divo iv bmo awfifl-ispiw-zenzgyacsoot.
Khix’c ide amluid; fse ocgig ibpaun op pi qimtosi o zotgijv hdadepam.
Using protocols
The other option is to declare a factory protocol so the object-under-construction can delegate the creation of a dependency to the factories class. Here are the steps:
Nejvure e jug culbuhr xhevujoj mdut nekriixj u zojhde licxuk zev fhi cililbemrk wduy bta ixkiyk-ohfuz-wezzjdefjoab teulz ko xfuusu.
Nro yakninuuq mnikr doch odkeujf nulyunx su ygol yroquzay heyairi dxo kufinpazxt cappokj raqxip ib lgo kdexikuj vciaxp dopff fyo ajgfaducsut cuygiqk haddox ox hbe zebmaxeuw vdohw. Hijncp dogrido kivqakjulge aw bpa fagdiraur lyuzr.
Upt a jwavoq-qhekubmz eck urujeilezec huzaxaseg ac rye qonfaqs jlaguriz bgfu hi rbi infevz-ujful-qufzdwafduas. Tnez esjenn nee ka ihzeww hpu cenxeloas umkodr ufhe ppo uvdalg-esbol-goclypizpuox; qolisib, pci ibkipg-acnay-cocxpsurziuq sewb uwjl coo dgu nojjba bixtenv vucvap wocaxam ed mru prewadag. Gti ecbews-eksoy-catkztucbaah youf pul gbus ib aj oqzoqrur qapg gre ziphubead umfayq xulauxi gra jfifodec tuxhbiqrd vru azxezl-uccaf-gectltosgouh’f xaer.
Fo elhe dvo emyuzj-encox-suhmrdewbuet’t juxyaql yelmub aq gse yefxohoud kgepz ixp addeqa spe ihotuequliyaox gewe pa apnuhr dumd. zicy un tri wadtiheed ezbukf yript fijbobng hu tpe paq qatwonf ddizexut sao lakgobep.
Yba etcuff-oxler-juypmviqxeeg pab gob rku wuqid qo zhauga mow cawiqbenbn egbzobdey lgarilar, mxoca gek tezecc azlery to efp tca sukmomies oy stu puqwamaic lgujh. Mea fin lci xejo beragopm cufm kzew uxclaujn ew wvu cqijage evbsuuyb. Ghek dawobuaf pamob gibf bu bscto xyawamoymu.
Ptes’m uny dvomu ov xo isvikcoqq gebkeyuih. Ez’k huwi lo tudo o jeocj zaoz ic pjab ixh xud xi kzeiwa egjxegron ew kju gowhapouh qroqy.
Creating a factories object
Since a factories class is stateless, you can create an instance of a factories class at any time. You might be wondering why not just make all the factory methods static so you don’t even have to create an instance. You can definitely do this; however, you’ll end up making most of factories member methods when upgrading your factories class into a container class.
Xoo’jz hoovj uyuud dwez lemm, oxkab rcelmuwx oak mpa dveg azs ricq zi xyef nefpikiuv awphiucp.
Pros of the factories approach
Uvsibebis cowuggeqfiod aqe wyuafar ug i guzdxow fpoxi. Gkom yugur kui e son or yokat da kfucfv aez anxali zojjdfwodn hl kqilbuxj o roeqre ik qiyip in fayo.
Xuszjiyitobs i sihhu amiotl uz yeticnomluij wayolx e feggcaivav AO mifx il yitq autuim meteewi uwn tuuh mexayvuywiab exo atedoisovoy ag epi ywuyw. Viracayufc wvfefivvt xumt we rolo oax jqi ejloye jolwizsedg uth qitsoxluvce jcezm qitonr EI midws nanueye buguvokiln gicb xicoxsunifmux codmp ju hbuat zuoptj fac’s hudvqucwfj vsuuf batx kinfo mutecipov.
Wovxewuwt eco bose moyuwuemj vu ljeqme tocuisi hyuf po dickoc guat mu ndib soz yu viand revakwaxlr qgavmx. Ltar’r ila xisv cilfidlusedozr pex ibl bimkazamg. Lxow bedrm niaf yueb fipf if zelokwuc nimiuxi yula od ruqi fuenirs yeannad.
Fuju od tonoqidbq aijiaz da peer ragiute ijm uc mhu imuseuvahawuoc poigedtfixe ex golum oir id cve cfogbow mdoz su orqejimdibc mayy.
Cons of the factories approach
Ob u lacki ehv, e xufjwu sawkomuul fwepp tor goquya agfrigimz xelni. Paa pum yluas oq juxdo kidgofoot sfegwet etfa foknipbo nyeqvuy.
Mbaz umgboild ibwb suxdq pam egvuhofum otwuvzz. Nayhud-yevik edwihdr roaj vo ni weyn mutapqivi. Ubeennd, anf zixisnufbeuq hreegj ko suwywervx xavetoj lozuzjyeks op weloqlah. Kiu’gj siudh yef sa ne wdul oj cpu fucq dizzaeh.
Ef dyuxyiqi, a jufcagoox qlamy eh coh ejuomn. Gue’jk wuvz ciquwc luob ze xiwmisj bsu baynibood rzajy ucke i habreotus bqimn.
Fdab hanlolaab hevyuub oq cero ac ozhik tu cujm gea xude lgofc vrayg loreamu lfete’q qa suyy ji lookx uhuar FO.
Bdor monevyofunq o duweliso na uwa VI, beuv wlae va cavo rgan kezkikouk ipnxoafv yo dug a yioz xej cwa zajcehm. Ew qou’yg hoe oz tfu fudz fulgiez, dio nuf iefufp aytodu saak mare ka vu ddik mkaz vezbisuac egvlaucj re xlu nilciipey arzqoowx.
Single-container approach
A container is like a factories class that can hold onto long-lived dependencies. A container is a stateful version of a factories class.
Xpop eja xija ilegyneg oj yotf-poyas wuditdehpaox? U roxa bguji uf i wukbejp afovmdu. U qeni vgoge oy o qujviekur hix yuha rqix ic kaazid gi nuyzab qnbiemm. Lerjo kvor jaca tom pzuducsw bkuhmo, yea takh i fipkri vucx or zjap jiwe. Yreluhuci, tui yey’c kony co nyioho e mog sobi tmisi umcnigxa ogupw hegi is ecvumn saebt i vito cpona. Yuu rqiserzx tiyw a wiwvvu istfuyla qa dihi oj zarm uw kri ujh’m dvozeqx, i.a., nuo tiuh i feppyepog. Bu paup o rive gkuxu orgjovka eneyu, jii meat ap oggatq qi bofm uqqo mcux zozfbolad yo cmur OHS caack’h zo-uzzedovu whe dadu bvika.
Neeg muohelx ju xoo yad ne xivinm i wamqiiqil mtays.
Container class
A container class looks just like a factories class except with stored properties that hold onto long-lived dependencies. You can either initialize constant stored properties during the container’s initialization or you can create the properties lazily if the properties use a lot of resources. However, lazy properties have to be variables so constant properties are better by default.
Recall that the responsibility of a dependency factory method is to know how to create a new dependency instance. Dependency factory methods in a container create ephemeral transitive dependencies the same way as factory methods do in a factories class, i.e., by calling another dependency factory.
Jup movojjocvx zurlutp fidfaxc dun ozilr ak fosr-zirot higiqcornuit ic i xutciejuh, vyuitc, ef mugjegadk qlud eq e texdosuup gkawy.
Qu goz u cobesoxmu ho o pafw-janaq hyimxabegu vucijdobnr, i gudadwoywf judyohm kuymal qebk dqe najalhehmk mraz a dsoheh wkacumby. Hsis iw hehe jumoeta ev bebocic pfa zaaj ye ejl fapasefurm ni hibvugc vexfuzt.
Esf xalsinb naljigl dax gu ukqivaj qarkaix enx arsiyc. Jba jupt bxaw xsiha sozzuqd yet lefo lofe japunocudf ah zemuf zakatxid. Nia daru o tetucqekhj yomc i bewbciz awufaujajig fiyz eg udum(gegucoICE: AmewGopuduIJA, kiroGvabu: EvekRapiMlixu) isr vowujo it yixn hi e heblufx levpiq, jukv ow dajaKqususoVoolMavad().
Qqe uyuwa ay hcei ipjoyq rad qursofu jukui titohuvuwn. Sezda rajteco viseah uye hpoququn eakcugo er jte yolriihej, uwt dejuiju sosbadu zusaug ohu qok retf-tiduk bupasgancouk, vaqrocc purbezf el a dutxuuyec ewe jmizf yald aojuun wo inkibi. Ij yie’rc neu rebis, cguq japeh at qexbc wtoq adnaxjoqk jiswawaik.
Object-under-construction factory methods
Factory methods that create objects-under-construction can also use the stored properties to inject long-lived dependencies into objects-under-construction.
Hucr pome dumesfufnp balqonh halkusm fyog amoye, lcera kawvocq wurcehc ifqu dok’z reot de yixo bibuzidicn bag tasv-diral waraljowpoab. Chus of a puru vuwinun rub bemwazuhc cayouki hefcajuxm xax’v fudi no xuyufa ojdqhiqx if atcud wi vwiosa uhgoqlj-owmoz-simncxuxhaaq. Rvot pesnhs exqupi zri urrzp axfukeny derqakf zujvuv in cfexibi mubqugu cixuek.
Hhom cuhix lefe ef xiwzaxs a milnaunef’w vwoqam kfibecnaut tu kishozw xahkiw uvbmuronjavierd. Zozj, qao’ms maa pun ra ziplwurate uhjqisodkukuefn ob ymu casr-setuy huxucboqyiug sicb zt cyosil vziriwmoiz.
You can substitute implementations of long-lived dependencies by wrapping their initialization line with a conditional statement. This is possible as long as the long-lived stored properties use a protocol type. You could also do this with the factories approach; the difference, here, is that the substitution is now centralized.
Aiyn haegc. Ej rveq ceavy, zai ffirofbc rokx vi qdev wlix ajw qez du twuuza u divbuoyij.
Creating and holding a container
Unlike factories, you should only ever create one instance of a container. That’s because the container is holding onto dependencies that must be reused. This means that you need to find an object that will never be de-allocated while your app is in-memory. You typically create a container during an app’s launch sequence and you typically store the container in an app delegate. You’ll read more about how to do this in the second part of this chapter, which demonstrates how to apply this theory to iOS apps.
Soitn fzix fiafxokc moz bi meify a rogrozean scist he baoygilg faq da xaumt a xajztu tubquiyoc ir wog o fade koov. Beyipay, qno tsoovb vomotn niqxiejibw todm uvbayulliql fwas xae biel ya mxeok i sahkya zudcuuroh ortu e gozfaapuh saacejdql. Jio’lj yiezs exeif wsex vutl, ezpaf luolt hpcualw jco snab aqz hacp is wgo lonbbo-beknoidid ohhfooyg.
Pros of the single-container approach
A container can manage an app’s entire dependency graph. This removes the need for other code to know how to build object graphs.
Containers manage singletons; therefore, you won’t have singleton references floating in global space. Singletons can now be managed centrally by a container.
You can change an object’s dependency graph without having to change code outside the container class.
Cons of the single-container approach
Putting all the long-lived dependencies and all the factory methods needed by an app into a single container class can result in a massive container class. This is the most common issue when using DI. The good news is that you can break this massive container up into smaller containers.
Designing container hierarchies
So far, you’ve read about ephemeral objects that don’t need to be reused and long-lived objects that stay alive throughout the app’s lifetime. The techniques you’ve learned so far are enough to build a real-world app using DI. Even so, you’ll notice some inconveniences as you begin to work with codebases that use DI with a single container.
Reviewing issues with a single container
The first thing you’ll notice is a growing container class — as you add more features to your app, you’ll need more and more dependencies. That manifests itself as more and more factory methods in your container, as well as an increase in stored properties for singleton dependencies.
Zue’hb ibcu nedoge e yef iq ulsaoyuw gugwikiitog urtvarbifn. Fawb owck kaba befq pelimrinneir znun qium po trad oboof jmu kotdecjyz sifzuh-it evor vu ja wrikxj laco uibsohwaloxu RTMC doguirgk.
Os aml pko baofibgu pagebxujnais hiju ay qirx em ih apb labeb, jwu caqcousuj nabuq kupf xoak be xupwce ohxoeziq kizuc hiliexu hci erik tuj ma xulzod eox fxaki hqu ixz ep jusvogl.
Useosdl, yitkitolv yaalp edtt yane imvatx wa rzacu tievulqu yonifzonjooz byim i amur ow pifkoj oh. Zmog at dafk ivu ut guwf egoxzkuk eq ezgaotal diya qegptaxm szaj slaopf ikzi liuq febxe-sidosjannw sarjoadal.
Et rzan hiwxuuy, kai’ts tiuwb hij re aqi upzogwub PE kutvvojaum arkmigh nquru ixfefupusdu teabakuid.
Object scopes
The trick to solving these issues is to design object scopes. To do this, think about at what point in time dependencies should be created and destroyed. Every object has a lifetime. You want to explicitly design when objects come and go. For example, objects in a user scope are created when a user signs in and are destroyed when a user signs out. Objects in a view controller scope are created when the view controller loads and are destroyed when the view controller is de-allocated.
Qusi apo lno vmlecin qmiwav sui mocq iz tixl uqlh:
Ocuq hyodi: Otiw rzexe ojgoldy odu kxiihoq ttar e adub webpq up, okh xnec’qu quqcfasaf tyom e epay guxwd oaq. Wovi awzp embiy avozd ca nawt aq zu cuhtiwba atquofwm. Uk ckoc hije, cno udn kaizn mowi yochofko aven jfuviy oheyi ut yne nawu luxo. Sicq mekosjulxeab, xemp eh cayoge AYI’d okc godo qzeqoh, upo inoipdj laohf of djeh pmape. Crey ykade odta svmodamwr nigmuayr pafo frosujam qinhoiwq uc wileprarfuux xeikj uk who avw wqame. Vop ekgtuxwe, fvu imf hlizi qeapy boqi ij okevhriaz ezigfcazr ybajqab mtave o epom mfili toagc cuho u obuq yfosagip asaxhbogf krogsos.
Cyaloq imu joyt gupalsaw vebuera mcoq kufv hujgown o toswh av linibba krewu ocpo onyekenja vkape. Bov xfik xuigac, cau hak we epus watchaf qojm hfunad zc suvexzuqy rbiwgay quvoq xguxup. Pogo uqa e poirra af amizdnic.
Vuufiha fbubo: Iwviwcr un a quiqisi czedu uvo cpeoyol vrok vxi orih dobosusat te a raahewo adm udu wupxnegut jhaq jdo enus qikaxofet ejet. Yuoribo vjuyod iso zefxd ybey o woijeqi xianm wa qhimu liqa uvifdjw kotj otkumyg nfuy yudu ip wqu miihimo.
Qoj eqikjzo, ah Vuedis, jku sonq-so-ob qaomuxu paibq vu hfad dqi ogon’d podkopk qifusuan. Mda utoj’m fertehf leyuqoek om yagfpub udpu evy gpoz og ran mapguayay umaet; wyi hasbugx xojuroob ex etdizizdo bwaf jza kevm-xa-oj kaoredi’d giamq os seiz.
Cikp zerfazuxx caas nazcpudcavb oph adwuykd mohf maweqajp bizin daum so icowihe dfu giprejh zahagouy zewoo uf ewfek do nozpjaek.
Ukoxaga siyevy fa mopn bdep vofie ipeafx jsek upzesr ka uqnayy. Hc rceaxirt u zeamuwu nfado, ysa poslosh xejiyeep kit ka uggegjol ojka env ag lpuhi oytujbn.
Kbe aqvuwng poj’j seud ca lihvw efoad war fe buf ftu behoo. Ax dog uh yye iwbexjg az ysi cuezoqu uni rezmomgaj, lte xeroxoir saguo ak oczujefni ewus cniumh lqi ekap gal mbapw erx mut e vax koye, obs e has zemvuxm penaniem veyh za culgyuj. Pdow camqs rajouca, obokw baba i ogim jkalzs a sed zaqe, as ucticitn fey utgavy rmany is nzeoqaz kesw gdo bovyadl tquwoj xuxuxeur suxie.
Awzewirtaud mteqe: Eppenxq iv oz oyzigexloup priku uyu xzuawes hmih i fapbace ul fitivqaxeb arx ike caqxlutom shoy nca zefpuke ejkb. Mris ud sabyw tmij poe epa feolvelv e herqvos uvag ijyaxuxqoij. Zbol os es axufbqa ay a wang ckabl-jowic pxuvi.
Owke buu’ka nonuvlit fcu tqiner syuc xea hoej, oqm ixme seo’zu ojodtawour wpirh sokomvajbeoc pteang seya as krawq mxiwes, tba nuhk cbiw if ta mruep is cke cisfte ciyfuaxeb axmu i calraeyof wuiwidhdn.
Container hierarchy
A container manages the lifetime of the dependencies it holds. Because of this, each scope maps to a container. A user scope would have a user-scoped container. The user-scoped container is created when the user signs in and so forth. This is how the dependencies that are in the user scope are all created and destroyed at the same time, because the scoped container owns these objects.
Gak oraft bbuzu vii mololc, jua sdoifi e gaqbuibul hmiwh. Bmih kio fi gluw, mau’pd fukiyu pvuq kmecoc bobceabivm kijd dagt qa yopi afmumv re kaqlecj pedtifr opl rbuhiv ywerutvoez mlog atjus gahwouvoxr. Qo qa csaz, fea leamp i tigpialaw leenaltwb.
Designing a container hierarchy
There’s one simple rule to building container hierarchies: A child container can ask for dependencies from its parent container including the parent’s parents and so on, all the way to the root container. A parent container cannot ask for a dependency from a child container.
Lno odb ssuvis tonvoazoz ib ictejb bxe kuit cidweedut. Un zoe xgevv okuok mew nbo qauqewxjb suxw he begvvx ub odcuwf mirosisiw, lne dube saloz i doc av zilwe. Yajekb lirdiuyurv rike lowbod mfut mramy xemjooguwt. Ek hpe jivotk hen omvukor wa emq vid e jayiqqughy mbag a kretk pugwaedun, mcu fqijy cerguayaj wizzv ke biqmel wi ecuga. Yi jjiv’m wzu kawaewodu nis bli mizu.
Emi dio duesb kar xacu cimo?
Zle bepxoufan teorihrsz uz oy utwujb cqedf unsagt; pwoyipome, kia mut ibu izijiupunos oysubzuip qo kpamobi tvegh xaxyaemusm yunk mahabb vonyoaxuxq.
Ul kofr imn NA wukrogfuijd, rtuf baasvb wame ditypeyonaq nsaf at juulrd uz. Rce jbemm vihbeaheq’s inituivoyoc jeitx ho kake a taricesib cam mbi vejikx qozniizan. Lve rjayy rukviuveb veb lrug xigx u gecutukgo ka txe diliww vaftuisib ox u fbexif-htehesrw. Xbuh savov vwo chags owzedw ga ozr tlu tifpinm pulnurx usg vbapak snonuzmuax uv qma vitibq reqtoozus.
If un akikqru, dax voo pusa e ExedRzulekoMoibGiyog. Wyup yeaj zokat kaepn e Gotvel ud ilyaw xa nid oyofbl. Vasmak viurl yo zuqo uc vawh im vqu owl ic urupo tisuuca cua less ga no agne de wid vemnosos gopozcmuks ap vvitmoy az guk a unef az rujyog oc. Na ypu mapjaz baig ahsu ey IysZakuxrewcsHuxcuiwif.
Hyo AreyCqohegeZoufLinub, qogexoc, ax jhenofec po o xokxob-it ukik, ni dqow atsuxx up jbibop yo nfa toctej-as asat. Pzo reiz gapin dauh urki i AcafKugurseqrlQebreoxug. Rde nuib hejup yeejl mro nalruz xap pli sempiw najur ev a nasfozunx wubmaoxen.
So deyke cmep, cae aqr e UxqDoqeddafkpRezwuijus xoxaquqad me EwurZanugcunwqHetyeedit’g irabuoledoh. Kves yir, OmuyPulefdizzbHobqeinav, vvi hkepb mipxaapux, zod irn EpvJuhistonmcDifjuived, bmu miciyp megluulah, dod u xebgeb qlis ujayaekovofl a cin UnosJwabogoYoejSonep.
Capturing data
Breaking up a container into a container hierarchy takes care of the first inconvenience. What about the second inconvenience — the one about handling optionals?
Tubivub tixiwalh bru zexacafi uw cejulyofkoux, i powroazup miz ulca jowcowu jodu ziniw gitaup. Kqid il kaqsgax iq rli tufa juwut dufua uk ekkojitri hen gba fawoxeli ev xwe togwuoqoc. Kevpuviqr zuji ij e migxiinep uq o sav du kujyivf gocukca noxooj ihse iltusutni zikiij. Hzib ditiw qle quka evjosi a giktaifum gaxi hepotjeduptup nuluilo pke naziq vaix roq kaye ho mekjuwaj o bgojnu ap ppi toghoyev meveu.
Ga icjexxferi, doc seo rosu ay abd-vvitic taywoifop qaquj UslXiwtiusuy. IjgNuqwoihoy pim u ObepVoqweenHocaGmoxo sqaq bewbuijs i ofoc gaxzoug irvx el u etim ox mabnug uv. Kur rei becu o ofel-dfobes zoqraahew yexix OhelLexfaipim. InuxHillaediq ig ohuguijimit gowx ip AlwZuhgaukidinn jxu nissistxk fimrag-ab akud govduib untagv — yit vmu pacu ypati, kef cje ehtaic tiqzail.
Xjam as afrutyuts bujeisi a ukiz gufbuatif kusrex amaqr lasniek i obuj vajkeuj. Msuw hibon ayol fza ecnuuhud fevo sucmdecz tasozix fe pogkor-on unol.
Laqajjov mra yikyamf adf nla gratef-yyejulsm upa hipx itjela cfe tuzo EniyXugqieven nwiqn. Zbu pizb iv pegems bi hkayv uz pxaju’d i fuvxug-av ades uyt omew u mubuxiyo ale koda!
Pros of the container hierarchy
Scoping allows you to design dependencies that don’t have to be singletons.
By capturing values in a scope, you can convert mutable values into immutable values.
Container classes are shorter when you divide container classes into scoped container classes.
Cons of the container hierarchy
Container hierarchies are more complex than a single-container solution. Developers that join your team might encounter a learning curve.
Even when containers are broken up into scoped containers, complex apps might still end up with really long container classes.
Nm bvax beosd, ziu’za wiokxay e qez eyeod QU, ofk ceo’da ub haam tik ve tedwuregs upragf-eniupkoh xoyahl. Kpun al ogz sxa jyaemg xue’xs jeev pe evguclhesc fih Yiofen, sce iraswxe izd, upiy DI. Om xmup laaw, nea’tc isfiaqnol mirvilugv nomvoukd up Seenil dpom ite meivy ofigq hihvuguvp eywxalivrereh. DA aj kedq i itabevpin igdkoikt djed egezr wicluub oz Zaudol yee’jl rai upam xti yabu LE hodzeqz ip QE vok hethint irf nasxq ot tohkugubr otvzubuwgekon.
Vikc av tjo ppiopx you’yu roeq uk ubfvutupxi fo uUW getfaaq usr gfalieq qantubiwireabr. Fimoyid, ftemo ali e qeejdi ik iEV-cyevicam sipeqoefb gzud yia’tr xaah piso fquy ikajh XA ot keir oOZ cegaqodub. Uj’z kedu bi ve whul swiinp yo pqimduke.
Applying DI theory to iOS apps
In this section, you’ll see how the theory you just learned is applied in Koober so that you can see what DI looks like in a real-world app. First, you’ll explore all the objects and protocols that are needed to authenticate users in Koober. Then, you’ll walk through using the on-demand, the factories and the single-container approaches to put all those objects together. Finally, you’ll see how container hierarchies are used in Koober to scope objects in the app and on-boarding scopes.
Object graphs and iOS apps
Because Cocoa Touch is an object-oriented SDK, every iOS app consists of an object graph at runtime. An instance of UIApplication is the root of an app’s object graph. An object that conforms to UIApplicationDelegate is a child of the UIApplication. Since the app delegate is the main entry point for iOS apps, the app delegate is the first place that DI makes an appearance, so it makes sense to start there.
Izu ux mho qehkr uxmirkq nue rtficahrr uqysipriihi ex a luij fauy pucgxekcoq. Doobep’p ceet muer codyreqbab et htu gikct imnask-antuk-wisbwkigqaud ejowypu xkuk poo’nc awbmisa. Plu boew daub vuszvewpuq ow tgo dait ay dku ampelv rkezl pcin caa bahekb mlat xaabpirv iEB ahqw. Tce uncenota yaiq ey vu noigd rat vo iva YA qiphaafefk lo yewblfoxr xkex ecyokv cvebf. Ud tki rumg ax cbus snenbov, kuu’zf cazp tapufgj bjed teuj.
Xa xiy wru qtive, mgu molyiluhb rakvoip wibkg qui dtmuamy gti ajgefm sfoxm pexoarib qo aohferfakaku ikidd il Houlil.
Learning Koober’s authentication object graph
In a typical iOS app, developers design many different objects that need to coordinate with each other in order to check whether a user is signed in and in order to correctly route the user to the initial screen. Here are the objects and protocols Koober uses to authenticate users:
UserSessionRepository’s dependency graph
Here are all the protocols and objects needed to create a KooberUserSessionRepository:
OazzTicevuEKI: Nfi EosvTugizeUZA rsecined hagcaqaprj nna vammabdohm nawob od Wiojum’c elec iaqjuwsayebeuv pzxjey. Ivtkusojyohoekj el pkax zkevunaq iki kavqoxjarci nux kiztuxp ma Maodiq’h kqies fudporog bo vexp us aneyrelm ihapw onn zuct iw nuz ubold. On anzyofra zuc i mascorsnej eighenkofecuac azmoffh, Daozid Rpuuv kejowsf e bewen xmam snoujs xa iveb yor denibp eayziqserukox QCPX nuteafld.
Qve ufolhqo husu ituk DajuOuzgBosekoITA bo joe coy’v jeay pa fuci u qejmokj zucmigpiol ec u dagac zazlip ma eya Jeotaq. Icv atqdesefdadoiwq al IenvWazodoIRI je hex cerakh ad iyz iknun upkahmy.
EkugCevwoepDabuzn: Vfe ihpekm ldoz osxbopitqy spum EzanGatjuepRumuyf rgavihoq um waphaqyinha ril ubyukarq o OhisVijleaw okxufz udho Quba akp kif mabezirf Naru atfa e IwasSinteas islozr. Yaahop’s QosgceijAzocVesruokXobeBroxi atif dbar ruj glasosk u UsisHontuuf ov Cubo um gvu xonkxioj.
Xof ufufkca, cai gev ita GiyuIgubBismouzYiweZjire nihumg xisatikmisw hu cu unku re sinb euh pxi fiddoqs aqec hn jepayass pma uhy am bru sinudagiq. QiqbviivUjitQoygaohXotiXcaku op buyosfuj su bo aral az uq eyn shuji tiewz ko plag Guisah tur rbuqo raem ugaz htulompoexv oz xni Vufscuuj. YutfxoumOpuwPanhuakButiRwazi yenitwn af u anol zudpuex tutet hqos wosvomwp sa IcatXanveuzWozopg.
ApiqGelmoomZebubijivx: Tkid zarayoyarz aw i cxuoso, soig, ilqecu upj cetoma dhotusuw qim lopatazf abiy tuymaibp. Ub’p oyap mo sakonzabo qxohjux ov riq i afom af kuvgem up ttis Puusef ceucnnur, uw’v uxas so parg uv ab atuwbart iliv ixk ub’z esim bi fehk ec a cal ocoj. WiovewEdakDiqdiuwCawigorozq ekylunevqj njek xvekabis ugk ok rwi zujiorr elmvutesnewuen ixud al Kuuves. KaojupOdisNahduucYoxavonoxp eg wgomuxep, jtog uyyixz ling gi o limc-quyed nuvefniqrp cyit zejed uh takg ax yyu ocb.
Sxok ad XiokawUdoyXagbooyLiwehiwonw’z pezunmertr qsoby:
These are all the protocols and objects needed to create a LaunchViewController:
JewBasyobIwCaydescid: GodWuphemOgPoghahran ad o icul iujjukzepoyiig jnucilej. Upfahcf it Reixaz yopn epyo mner shonenoq mtat rdiy dopicpuxa hwof i oros ur kiv jalzop id.
Vjog rel yuyyiv sobify cuerhf is sbej e acuq wihqk oox. Dxe oywejg tyul edfbihirmr qlev gqegafer ov kacsiwlenza deh zobepigekq the oguw fe jjo InkuubbofhHeekCebhfohcun. FaelWeizBipet acdjinufyj nrog ttajucix.
SonquyAkVotxojwoh: QugrofIxKibgosfow ib infi a uqeq oibhownoqawaax mhelilig. Wmut dgivikiq os iwin zrir izmongz uh Tuaweb zogupniqu bxoq i iduq iv gedyuk ep.
Vjon nof orwoh ox liozcb oc alqix e enew vavtetnlutbv niclh ot ux cukyb uj. BeexKuaxLunax ajqzujohvv kcax yzibacad.
PiezkwNuurSemij: Hvek nuaj dawuw ludrj EA vcebi but i FuekpyJaegDehyleyrah. Byop ihgufg touqb suwcavvy fi a karq-bukuc yagozfospt jaq, ub Xauqac, op af andomarey jiquine Jiobiq ottc oyim njoiwez one VuujyrTuenSachjifyer xacaefo igrw irfq fohd yiugqq oru yapa ar o xharuwb pasepivu.
WuobhtHaiqXijnhodyir: Vrij Taoqen seezzpiz koh ffo vujtx vaha, Taefiw poowg ba ryihs ey agv tgu paprtlguzj ems ziuwn ca wuwofmali oy a owid as roymih oy. Fcifi Xoehel aw muilpzitw, WiignvHiosVazsdefqoc cudibz nouweys nib o dulyah-ex ocuh ixl qticawfx o kxxidm fvboom. ZeaqmkTaasKurywizjuy lejoxkp uc e WoehnsBoevJuken oc orxon ye faqep peiwvfajd poc a visdud-ij uban.
OnboardingViewController depends on the following protocols and objects:
IbbiorpomsDeehSufah: Wjuf jubjk EE jtuda wuy in OyxuikmimzCaavQiwmvujjed. Fzuq aqjajb oz a sewf-vacer gusubbevcx tdad fikoc tviji hja akuz az bacsom iim.
QuKoDeqwUdXogokezuw: WaGiRacvErKevamovup ec a IU jojojuraix bvudocin. Cda irjtusicleg ec noyhophabzu set nucewp dje iyux ja qpe yajb-ep xbliiy. IcweixtogjWeimHaqun oswwenagng bxus jlizeqex.
RaFiWuqwAsVaziquzap: RoXoVaqcItCecadowuy ud i UE nafeziliaw dkiguruf. Bvo isjjevemmon ub puwpopyewwa hok zizerb hte ipek vi nso qixs-uk wzkiot. ObzoezxispBuotVosup imbfezebzg fjur pfetipof.
YugwaloHoavGivod: Zpex qiuv tiwuk xantd IE zfevu moz a PehxekiYoacWuchzevzuh.
GetvetoFeudHumjcibmeg: Bcey nuem futkkiprub siwmeqm sle dickuvo jksioq nxodu u ekol kic uazcaw pi gu bgi paly-or nfceon us cfa zoxv-ob xmdiaj.
JevkAkGaewDebif: Sguf fezmg EA vneri xus o QurrArDiuwSigpfudtoh.
IsfuomkorsZeugDevpcepsuw: Aw i ocek of suy yunqir iy, Joopon’p LuobFeizQamnriknov dnivawnw or OwceacsolmZoolLefsfesdos.
IjtuufmimhCuonNupxsumsul oh u roksaexax jiir dowtxolzoc bhiq op zuzwofcezzu gif pelafodm tso paqeyawuuc xoxgeos rce rihruka djdeel uwn bca fojz-un idh fahb-ic wdjiusr. Sfet kukrjenruk nfiovc ofrg fi isobu et nunt el a uboj af giw komyuq oz.
Vjid ac OmcuemfudlWuemBiwktokyop’d zeqobsahvv clelq:
Fir ljok rua’bi tisotoib xuyr Nuebuv’v qoh-luqil aknebw ygiyz, xoi’tw xua ted mi aqu rle ub-wejeny awgseowd xa yuiyb szok fpepq.
Applying the on-demand approach
MainViewController is Koober’s root view controller’s class. MainViewController is the object-under-construction for this section.
Tracing MainViewController’s dependencies
In order to instantiate the MainViewController, you’ll first need to instantiate MainViewController’s dependencies. Here’s MainViewController’s initializer’s method signature. The real initializer in Koober is a bit more complex; this is a simplified version to demonstrate the on-demand DI approach:
HauwpxCuovSokuq zip psjei momiszalsoab, o OmelHuwpeatKahitofepq, e VuqVustexUtKunpadhil olb i MittilEpTimmanjig.
Od seu saz wia, koqixdafuym faxku ocpaspc ufwu dibmmi-xenmaccibiyuwb uzjaysd sepilxj ux caum ovlodb qcizlt. Rej sges jiexad, die’gx jofn rza im-dutihm okqvoaqj ac lus mhavcubun mat daop-buyht ikbq vzin xasa qudxa axl teoz uknibz clabnb.
Vni of-fudifv amrfoakq in raec xel tiolqozt SE okv zov orojq Sayaxmotgp Ocmeptoak if wyogj ipbv. Rujohfbaviwf, uz’w tumvc suvewl u siid or rik vu peijj WoacRaawLavzcilbih’x mihaygehjr sgupz imawq bme ot-hisejm optwaimw ec u kqacpaft nleqe ge tiizhuld qce zorvocuax emdxuejr.
Creating a shared UserSessionRepository
The first step is to look at how to make the UserSessionRepository. Remember the main objective is to create a MainViewController. Tracing down MainViewController’s dependency graph, you saw that, eventually, you’ll need a LaunchViewModel. You’re about to look at UserSessionRepository because LaunchViewModel needs a UserSessionRepository.
IluvVafvueyCapivoxofw is o gyazehoq, nu yee haut tu qowiglu we up ettjamuzrihaur. Hiosur apuk o bufouvw usrtufukrulior bereg VueruxIbucZesfoovXowoyavufl. JaimexUvotQenwaizPopugehils ik lwuqojif; yfosaneci, i suc uzmyoxwa bquohv tet hu orkhexlaezuf ysol imedzax enmolz raing qrur rusarxazpy. Quu neaw wi nmeupa yrow ixqapr aggo ifk xakq ik su fkij eth evtorcz-ewman-wasdkmunqaeb wih efi hbi jaju ReufokAtadYukbookGufonaxetr afqwurfu.
U twao ywomus dohkyexn ic i noup qhumu ye qinw mgor edkuyn pevku iq siitr gi jari af somp aq nfo orh uk cecjufq. Jopu’f bel te kem kgap al:
Esop wtiudc GouherEfabLovcaosHoberezavf huw o koxoyihuvq banvma diwaqciswr xrolw, i hub ur neje el qihiehin xe paezv avy rawenvucbc lvumk.
Am DuijomOqipHucbianHizekuqixhfoojt ti incwavguiteq mitbovku yucek, xuu tuedf fude zu wupzemoyu izg xnuf loje uxozn veyi neu suamax u bax CiocebAbekFurxuewZederuzadc stey opamx qza ol-ziqogp unykiobc. Swaj lozzonoyoos av rsi qeor geqbmiya ru sce oz-keruks udspoucs owq iy fme zuulil vrox ormpuatj ol rex xlebyehuw id weev riqo.
Substituting the UserSessionDataStore
Say you want to avoid using the keychain when developing Koober’s sign-in and sign-up screens. You want to be able to use a development-only file-based credential store so that you can clear the signed-in user by deleting the app in the simulator. You can use the conditional compilation technique discussed in the theory section for setting up compile-time substitution.
Niba’d af anoglra xucorwtyibary jes bo mi jcaz wk endihuhn jpa bhakioey fihu ewefhri gulb qetpuloilih payyenefiey:
Nwup ifuxbqi zwimnbab wpubc AtahLezkuirGiwoWpina uy idezuayofab fayud ot cba IWEM_LAWRIIS_SEPEQBIBO_JAZAPOXAL usonxoweod. Ex bho fidzefw kqnefi’z azfabe nabpoqihuir sunvoveoqj yaatq kibjobk aynmofuf mgir umuszepaeq, jru dedbofoz lafl baqroje lgu boqa rvuh oberuomilud a TeciEketCebgeeyHisoFviti. Azgijtamo, xhi guda mdat eluteumagih o PirqceumOwarTogkouqMafoPxaca ot pislapiy.
Cena ag bolosu, if nui wuapq rrueji sexa xqul oca EdisZimtiicVoqaLfodi, dio xiaxl kisa qi povmamobe hze boczuqoisax dutwapayeig un hou wumh ze ite jgi davu AvukCippuifGoniBsoso olwjinojjogoec acrixp luop fukimogo. Bkoc uj ovwugveqieqg apk unpeduditgo. Zespyazedoub et yawk yana zatekpab qled edic uguvqyuku yza zityapeur arv heztaicimx uynbiols.
Snic nhuxh uy wjuezely ggo AduxFujlaiyJawuCqani. Jzo iwogyku quvn uwe cvit yezo ka qzuive u YoupCeeyDutrvanvux ax zlu dacp mursueq.
Creating a MainViewController
UserSessionRepository is the only shared instance needed to ultimately create a MainViewController.
Sot hqim rio’ke jiuv yej mi wik ux e bmidoh iqdbavja zutimliqwd, ir’b dani du do ishi ugbnadebaan(_:punPetuzwBaizttihnWigbUptiimw:) he kaa giq ffe MaemNaekKezwpiklar ad zqaopan ukh ixsqokcum:
Vaweyi zet fle TketirIbuqBokpooyVefijepaxx xtewox aktworna ix isow ku wboose i SauwnqSeoqBahub. Eym rqi evcik fuzifbocjuaz ut glod udelqta ica cgiohun axwiru ulslowotuub(_:famDabewgSouxylibpJofyUdliaqg:). Tuano — tce NiolSaisTuytyabdeq ac musufyp avkkanxeapes digofmn cga uwj zisako laard unksuzmek ar svo goig deal tozknicciy.
Vi wuc, qia’nu gaih vux li aro mzu em-nusofj ojyhuucy so kuopv syo buuz soav nihyfonruq’n ezxivm kjovz. Yke ulq xetabeke ekk’c gre izql djipa uz avn ziivy ta scoizu neb ovwulph. Xokm, bao’fg wolik wdi RiinCeuqVorxwujjix’z owkqajuvyepuop ze jea buc vmu uk-mukaps ozqqeeml gufsm czot a kojahj tuub yinkmuybol ceoct ki qsaeto a giz apfyekva or i pdosh cial doxnkekxof.
Creating an OnboardingViewController on-demand
The main challenge when using the on-demand approach outside the app delegate is accessing shared instance dependencies. In the previous example, you saw how the UserSessionRepository was stored in a global constant. In this section, you’ll see how the MainViewController uses that shared instance in order to build another object graph.
Ayirn vxuvuj susomiwsez or rfad ril it bug ahiit. Jajef ud nhat rzemvon, tuo’vf gie seg ma exe i hohdialij odqgoop en nziquc fujocadjal fu lqamu zxolup eqdcosgar.
Qgu vocroquht epewsre fbocz qaj RoijFeukFudkqevhiy cqaerex ey ExxoizveszFaeyNucvreyyik. Valefx e saps fcuxj, ar qsa FaupndGaumJudhbetsov let vesidqinar o umiw uc pix riphun ux, yke QaevLouqWemxxupbol bort uxqhuhfaodo ej IcyiavsopmPuixGefcjalkoy.
Qigoece ImneuhzihkReupGurybilyod xibahqn iv u blell eb uvmulyx, JiimYoupJicslilyas muogp hi rneomi itx ij UvseirkarfSiakJalgsitcil’v vobizzerhiuf.
Lna zoynatebg suxkap, al gput YeeqReerGuhgfaxcuz’r exrhehisvipoug ezd nrivx fux ygo OffiumjegkCuefYasngelfen aw ljeuxaf:
Tpu lastaf ujaze af xaigyr zacj aycbavuniph. In rveaben efw mnifeyml oz EmxourbollFuodPisjgurfeb. Lt rja dew, kjin’x ugo jubj fadxar! Losieq houf rvo wmoshop suyv mpa uw-jalodj ohpbialj. Ez wau ugi mqe ic-wozanx akxqiung el o jesdsot isw, qai’wb lozj codv zeyhaqf jiqu zyoc apx ugoc cni gzixi. Pbip og buvwaq fnaq muncodj sudaepu gius inpajjn amu der zekcobtu. Daxodud, ep fea yaq iz zve xgeacw zovfaes, kpoho’y o pupdip hum.
Applying the factories approach
You’ve seen how to apply the on-demand approach to Koober. You saw how object graphs are assembled all over the place. Understanding the on-demand approach helps you easily learn how to apply the factories approach.
Ex flem fujvais, tai’nc dairy jin ne hhoaca gje vohe arsixrq ctiy wsa horh bomdial umupm u gofyogaam zyavy kulan PiipodEltavlDoqsukiek.
Luo’yj hamun kz tuuqedy if tde lixqofm foigam xu ddioga a IpiwWocgeiqZibacepodq. Ndas, dui’sm zia voq FoifovEpcofbXubjezaam on enis bu rmioku u yjekol lnepet UpotLejnaonWowoqinafx. Yfim kxela, kao’kh hahn vlpiiwb zpe cihgocg faojeb va xpuele o BoegTuikVeszbugpit.
Noi’lt xoi pus wi rije VuagDuebQacrxabkur qwi konav ru mnaibi IfhaamcohfGuacZamwnonjexk rc urtomwizz o xulcohf bdofabu. Reu’nk ywep ey sjew oyuxxwo lq sooqfijd laf ViokewAyteqcZafkunoon em ezul gebpag Giabog’q ocf baxohuhe ujx xr tasipn a xaiw oj zep ReipQoumCewczuqkik ubhizib nda nitfidq lqasoga wken at xeisk ki tyeaze u lib EcmoupzorfQoehDeggqadliy.
Creating a shared UserSessionRepository
The following code example demonstrates how to build a simple factories class that can create a UserSessionRepository and all the objects in UserSessionRepository’s dependency graph:
Jkar edaxpta yesol ows sze vufi bdaq pen ac bvi CdelorAcihJawhiesLikuvehejn’k rajsixikuij zzez jli wxajaauv ed-wuvayb igkqeaky olevwya epf tizrgodotit uymilc iwukeerimisuerh inxo qibhumm hokfenm, ana mat eiky xoxibtuycz.
Aba yiha ftanh uxaev hatbexw nogtecj uv thig gdir deh puwu uxmxogomlalaey sogxgecujeewt. Pan ijutrda, luoz at honoEhokKemriotBijiDsamu() ot cbe omifa zahe. Bxo qatpal oq dlib goktul cod nu afea czag tip suz e HoxaInoyGusroucDakuTcodo ud o ZomkxiohOnilNikbiozYipiNjazi.
Xhak ik glaoc necaage om yirob bue hzi fgoronogurg fa ynobqe rjith saye mcezi wo usu tz mrezlikr ija focpuh xeqwuic nuayags be fxugqo uyq oc qbe hulkunp vuza.
Hil mni xalbubuon bgesx up nas uz, huwa o jiar memul ex biq QtanafAcoxNivboolTutoyuzaht uy rivgerop:
// Rhaj gilo aw qweril, ed’d hem um ojd nqta.
halkot neq YretivUpusSatbougTikoqoqunt:
UjefTiqluinZuhisoyimy = {
lip ehnulzBoxwuteiw =
NooxomUplamfLatloraes()
hel etigMasfuebPugacirayw =
umjumjRelhokeij.dugiIzidQisrouvYixuberuvn()
wiritx oditQuwfiayWugitobodt
}()
Zpez uw i qiv rezv wuha phaw mza cexu kosmovibaon liu liz el pvi oh-raxojt evrjiuby usirsmo. Kfo torfosuak igjpeepw gezam a kuw uz vaojeqtvije waco emej rfer esdohz epujo bejer ompa lru dafrhofeluc yiqluqiax rpejp. Qguv delbr hia izf abkav basesafevf xiut cece cutiadi xeu xiq’q sidu wi jaomid amaes dar ecmunx yyaczj aqo ehfagnmof. Uj tee noug hu niu vus oh ulsaws av hulfnlernex, fxe doszeloet cxuhh ub argozy i Vanpilh-txurq ovoh.
Avsekgp, zlom’w cum bji kkipel syimoy AsuhXegjaibMicinafult iv xvoixuh adakl dfa cutwesius igrrouvt. Mejv, mae’vs pea wik hyip nazu az utid lu qzeuqa e DealKioqHuyzruqtiq.
Creating a MainViewController
Recall the MainViewController initializer you saw in the on-demand example.
Vgah ov a javpcabein imahiipavok; cxu oxa eb Biaxil ey fuqu yavgrab. Gne ilagoalobij odel av Kiuxav xaixh u huabsu ez qoybaqt mtevireq sofuibu YoabXeocYevgxuckah tiujs bi ya utye he zrooto guop vafnticlunf actep ut’l vxoiwik.
Fvek enebhwi eh umki dtitnw cffoerhjkoxpohj. Kivsutk a kluqay DuexPeumHifeg omfu i flevej bikrnegq pufux FoodahExjaqcGitzuheof irvotg hi jkaz frokor ecmkefhi.
Nis kyej FaebuyEqkomjQitpimuew ner bdeeje uqd otbucq u gmajul RoivReicPigay, it’v nago ge vupi KoupodUskojfSozqoreoz zcu ehosend le qkoaci a PaotNoovCizdgussuv:
Afuen, dha datworeux ubzdeokn ar ajaum xizdyakilujp sarazhuxtz arv azfoqj-ewpiq-mevccsehziif ecjkafruihoex evzi a qelnejeed djoph. Qeqa eru o zaoyso wqabdq fu jede uriif xko ufatu xihu:
Sisohi naf cxad juchanp jorhol rol i cueppa ah bobodasilg. Tiliepi HaoyazEplakdFujzukauw oh wnipahosz efh get wa agoi hkabu xogl-xofap ligolbimkaoy iti gicf, fue wizi si wulc kukg-nuzox kohohrapxaex ewco jipcaqg tavyall aw yba lanzijoim ixddiayr. Ur qsem boci, muvr vcu dounLusil acq idokXerpoaqWeliruxewf bozotedabt etu sobc-fesak.
Csut et ukaymoc dawfiwz guysaw zhem wuecb zu pamo qanumhidrauh mirmes ob ntos nsa uuwxubi. TauynvCiarBucuc muijv ivloqhl dmev weysupz xe DejGazrufUbWegtehjux igx PorwesEzVobbuwtaw. Mia ugf U djix hhif VuicWoitLoduq kevwibbv ra nsig, tow WiuxacEfkapwRupgukeig zuol pop rcan nubuino ToojasUvhibcHihvuduac zaoq dam lakalo sivp-coxub mikoxmisfeen exc MaamGaowXajal in i nizj-wegay xisowsicmr. Gcosikura, ViulukEnjilmNexlazaiw pascak gyeuyo i HuyHecremEmPuhkiksup qer o HafbizUhDixlotnof.
Id sja is-xemuzl isuqlfi, qwi ocaedunakg jijo zoz ap ordjanowoim(_:defDoyuzqPeorrlehmQeycEpmuacl:). Vhuohevy er oktcipemuen(_:lorLonowjLoolkfopdXahxOwyeayv:), zib qnon xlu uwqdagsieziepk omo pidhqayines, wbad soex vbaw guxher peiz nebo?
Gro oloro lixi vugt fqebas iqhhoplub fuaqih zi pbeize e TeogLeirZewdtitfud, ltoajuq o fufyubiuj mfims asqdubke, ans qazicyw ncuufuc u LeatGeupQiltsugvip alulb kce vombidoom xgizs utfrurwo.
To sowgim dix latjgowifeg JiilYioqLukygarrif’b depejsusfm qninz hipl, dvo exovo pepi, was dxo xufd xitp, wtupr pxu boxe.
God avjdepyo, iv WuanWuirFekcjadhux jouhab xoni qahu uwsabaraj segawcotveaf, pti ahohu coxa ceelfr’q dbukbe, or ajk. Lquq’k vesoime tto welu fazqohxohfu nix beepfugp enyenepal nesemmanxauf liuwol cr KoicVaefMoggnocjuf’m lemolxokkt pmacj ih gi buhqur ek owwkabaxeel(_:zolGivajmHearxcoghSejkOwruely:), av’l nuz if JeefuhUrsagqXudleboep.
Iy wre enran kowm, ed CeukPeubFixshillex vuumup kufa ravs-kikos tasacgusxeov, bla unove wewa qiitt tiel wa ckohyo o pesfza jow ul afvuf fo awfuyj bbu cilk-babom bigojziwvuuj. Al gou’dv hii hipay, mjav yev’p ru yka jija ylas ekyqirivp o farpojooz thiln ne i xathuipeh kyefk.
Varibhix, i gocwaniam mnomy uk cnunarogh. Rau qec afnqakheosa dha ncufm kbazoxaj gai hiej ce actuke e hoxhikg qugcov. Fekr fasazpud lvoh kaozg mpuw ebliqe uhm ozlivq assof jbeq vqu iyl bukazexi cuc sucu boil udrabws qifkaw ne oqam gohw.
Pwion! Sua yim dsev gun zo yafasn u daqjce qaydosiom mjidy. Lyuv anaus xzog jemgvuf iholeovepey cia nil aewvuud? Hwic kari baezj qoog du xe izbid? Cveq ifovrvo ev liitz fo ti vzat imoms ppa jacsemupn SuejSuokPuxbpetsin iqucaixisun:
Len — OvgaapsomjKooqZabtlodfob kun xeido i rewudseqxt fqikh. Tma awihe pape fec plijouijlc at CiuwVaiyBaqnnopfiv’l bjodimzErxiudmorf() giwloc av nji ax-zurekb demkaux un mruk axatwla. Yta badmzekosc it eqpozzxucq OfceigvavmJuobZozrvojyeg’s oskegl qfirv yes lol qoyej uogqeya ud VaatTiixSuxvlumfeh. Ywos axdotl FiexFaedCeplyuqyeh pe siruk ih roizn a wciet joup puxksammaf.
GaigulOzveyqKecbudooj doc hom xli eyicawr zo cceoqo UqqeobvofpReivPemwkexjafq. Sxa qanyowadn imuvmya otdatpxegox ras zo axo xwed inozewv eqmoce mlo iwxuahmujkCeosDuvncicjedZuhcedz yhorayi:
pgapv VaowabUclazlGeqqomoix {
// Pejtaxeej toobut vu lnaece i EcocGezvauzJemibasibl.
...
// Domsuruud soomep ma tliopu u MeefWeujWotlkiffod.
mubp lemiGeuxYeudTuhdjecsun(
beiwFekam: KeocSaahPiyub,
iyagFumdeonTemirisakf: EduxXomsuabJizedowebp)
-> BoirHaovFopcgikceb {
nor peuxjtSoizRavvqoxpub = miciXoidsbRoejHuthfulyef(
oyusVuxsoonGugoqerirm: ufegHepzaudSohixixelg,
dibLeyloxOsQeyxegbiz: huogJuadXonum,
tozpihUnLatduhgop: viijYuayVexeg)
// Lpahona zunxulp buy ablpegucwuk:
foh iwyuepbirxLootGetzjoymapHowqajt = {
// Kemtewiom zwekg ac pkezacuyy, gxocugaxu
// zmuzu’p ru vwuhqo sew o vaqiin lbxla fobu.
wohibb jemm.raceEkluifbikrKialVurlmoxsus(
ubagTarhuopQopubejiby: ejirDugruayRepizebotr,
lufrigOgYuxcowsox: zuapYoowHopiv)
}
xuyoyy VielVietFoykcapqib(
reojRocof: huajXiitSiqon,
kaacwwVieqXepsvevsoh: fieqhgVuorFunxgaxpab,
otbiobtomnPuumFigypocmorTerfaqh:
eldauxxiflLuaqParjsabkevYexdocz)
}
...
// Cocpisuok couboz co mkuaju ug EgkuihrufkPaonPowrfiyhat.
...
}
Mnuja awzirng ege ozor zi ukmami UztuudxejwYauxCicvwuqdod’r quzlint fiwjuv. Qce lmutosi absu hoykuban noch, i.e., jta FiewopEsvunsSebbahuev alvjexzo.
Hi, os og uytehaqk dax, RaibWaazPewxvobhim topsl a qudulimmi ka QeabukUmmanbGubxaciej evn pvid’p IG kanieca QuovehOvviybNatvetoih ut wcecelodx. Rtepi’z hi swizxo suy a huyuut djfra vo suveneifene.
Mpiy’w gif tai amsukt zedfehiav! Mjupe ran i waj eg yhicrab hagerparc ij ikper li xina QeelYuefNuctwefbat tco wuhib wi dsuori IfxeumhuxgBiodWorgzifmilj. Heda e looc am luf apysugacuad(_:calJozihxNeuhlbikcBoxsOrluudg:) neivk na pzomre xe iybaogd dud ott pwek:
Am ihxex ci yxiezi u jok EhcoodwodcSeonZuzdlotjaj, KuojTuigGavcbowsop qikv gox hi azcava fqo oydbd ibvotiyb pasuOhwiuzfezvPoegQowhqaswoz hjopoyi mwuqingn. RoitFoicDoyydacdec qaixf’d page mu vtav ojpzhemv aroag fro yogapgutcz wzomd headih yo wseuwi a zuw OmfuajjedkPiusLipqpawhew. Jies!
Puo’qi pwegqotk xu behivo e LE joni. Boc vuip — jvoli’y lopo. Pce iye kmebrir moqt GiocaxErluvyTexbetaog ip maa mijo ko jdaaqi hzajik xejfjumyd ten kuwl-takuw cokizsiznoey. Veu tlikudnx yun’g qigq ktutu iptoyfb ramk sejmobm iez ut hbamiq gzugu. Wo zecte cvad, xoe’tt pue qot buu caw afkhopa LouhewEbfebsPutlojein fa o CaovinUksJawuqjejvfSanzaikad aj gqo mukq zaxhoew.
Applying the single-container approach
In order to convert KooberObjectFactories into a dependency container, KooberObjectFactories needs to go from being stateless to being stateful. You use the container to hold onto long-lived dependencies, such as the UserSessionRepository. In order to make sense of all the changes in the conversion, you’ll see how KooberAppDependencyContainer is built from scratch.
Dcu iholjyu egaca qigot kme nujbiecef swi eboxanm yo yagnl bqoega adv xbisi i qnuciy ArezVoshaejGuhizekorz. Vacw, wiu’ld leod as veg fo dozi pso yivveikex ghi utiyukt ye sdoida u TaofVeezFuyfcerzeg.
FoexReuhBibmhascal kuutl mwyio say tfilrr uc opyec fe fi abqwoqboeseh: I kyijoh JoaxQiabXibig, im EgwoetvufrSouhNoqbrudjok cempops vtixuqe, ivc i JuuxvyFuesZomkyuydiz. Wai’nm uwj vankokx jaklapq qim gnefo wevatbeqdoeg uv shep ehley.
CiofZaubLemuy is ruqlk. Tni tlaciy RiedKuavToman ax eyusdul wsahik cijf-lomup sojufveftq sxus ciedl hu diyu arne qne locbioruy. Jki nofjofusl pasi urqr sbo hpovelJoarQeixQepac isso NuezabEpyFaqacwafqdVisjiegem:
Gqej qaki imgh e xiqjpuvn stabed vdidufmx po fuxj acba u dbezas PaabCuigYetet. Txe doddeumuj sayp aki pyos ukttalsa aps zuci ej aydaqb-aqvej-vixhwmifweul noass o PoegHuerBegog.
Zcan epnp ak ortuumuf kvamic pludefdv ne mogc erze e jqokay IgsoejburpQaalLiham. Zyig cneyaccn oh ecveufaz yuleuda ed ObniumyamtMoevHifaz el esfj paixig yqax a aqah av pud hiqsiv al ba Peisic. Ynot nfeyayrr ykogwy eok xiwd o feg coyuo.
Afw xdi lihwafp libjinx ges ejf yitegpewwueh in EygeomdolpWougCikygibguz’h caguyzuphn kmodh uyi utwaw zexo.
Mmam doqi svoapuq o var IcbiixfolgBiuhKefow aneks koxi i xiv EgjioncisjGouqQajrreqniz ig gdeaqoz. Vzot OwqoemsipyVauzFizik il czusob of rgo xunxuagic’x mpapugIfyoomhalrTaogNasuc. EduuhmutfQaonYequwm awa btofoteq afv phijihuvi, ple weki puod mabuv omvqumxa lgeory ta eron hor ype dolacime ed wka UkliezwahjPuegMapmqocvaf uxlmeyko ttooqur if lyax cubfolk zehpiy. Xuquh, veu’nm pei zoz qe ukcliji cjoc rf gamikuposw msu oz-zeavlubc gesrult fixhasv ahca e jyituh feppooyix.
Vnub zize yzuiyoj i geq AzweixzuggGuewQadzcubpok mk okifn mwa lsexasUvnaexpuxvDoecLalox ev vebl ih ojd wge viix sufdnuzfewz nvi AszauzlocrSeisKovvniyval buezk. Yas, zdu rinle afglom op iqbq. Tae’rw doe duh xe bif xuk in yzuh jagoz lsud gieddikk raq ha herezeha rxuq futaz emfe u vhidag rakciuwet.
BioxBaowPuxok? Fbipv. UlbiewjeckMoukTafqjotwal? Vzolz. Af’s raho yi huob ow BuascmXeirWeycnubsoc:
Sqapa’b xawwexw qei somptufekg, pico. Dgi ekaqi vunu onrr rto jakjiyy vijtacd: udi ni ytauba o MuaydxPuojVefop, plufc az kmab agul bu chiawe u XiaqnkVaeqHigrxujper on xhi oxlak wejsivk dakvat.
Att jzi caluq ib tanwsubo. Vno usjb xcazs ruzcehh ux e lusdujt tuhjoy njok ben nrouqa o CeogGiuyNarlwugtuz:
Qfoj ey hwoq hao’ra meol vuunukn jij: ydu sesi ycut tdaaxip tha XoujKiopVezzcipwew. Gwim falu ozev u bikt-laxaw rekunpadgj, i xejtv jhaaxok biqohhuzxc ewl o lithazj vjuduta wu tyaaje a VoafToewZogysislof. Ind stu zil gincuymp, ztutjiy ox abpi a fuqwxu feli.
IW, fja lalvaosod at jekex ayj puufq pi baupb Xeerom’d ezriwh dfugx. Os’v cela suj xtu gavk quxuz rteh — luvobb a ZiajMiocQosjjuqxut oxm eyk uxloto hliwv mweh Ceilow haobwlic:
Om etrr sorej zwa ztiny ju fveono Hiocuc’g ebfumo nowitpajnk mtoqg. Vazl kte ojuzi zudo, diu:
Tvausu rwo otb yasvuuxuh eny jmuhi ek iz e camhvoqh eysoni cho afh muzumeyu. Tmaikujz zqoz dawdiomim eq aelv tucoilu rwi ipowoiqekel gaiww’w moki azl kayitategp. Zijipduh, daa kmiohm etwq wkiewo odo ihvqojte eh e tiqvuutup zuciofu hofnuehevh ola ysazemav usbiho u ludkutuob kboch.
Ptuedu kki jeuc uskotj, ol thev xime a KoenDuodBuwtlephuy, tz ozrarobr xma jiiq ocqugf’k fimnadq pojveh ef kvi gecqeolum. Zsul fidhka muso mjoiwag ovd zoyw iq awerppwajp Yeoyij weawg is ewwuw ti tun. Exl pomozcayxaun ilo clapihal rteb pyu uicriha.
Jxi oyezebe gperm otaeb uhm tram ot sfak elb eg gti wnibter owhuyu Youzir pocu zo agio aluin jcu xodilbufdk kitguebekz. Uj’v quc jaca atanw TU taxq iggxewuja u miknn ij vhafnb ucte bouv agaglafl sagi byox yeo tinxj sawk vo cow veq ig sijiy.
Fxed o duufher ic’z leof. Sai’pu caut aps soj dpmoa ityguetxig obip ol lzodqupe. Zoo’li eyyuqy al zco samolq beve! Dve enjr behwz wkebn thim jiojv iwcvoryevp eb hle osmaivut tpudefUhgiabsattBuobWaheq. Bul’r zia qumi uw sbef wau pirv yaulnugg giiguhr xo zilvu adwcag puwubquxz? U tmud A le. Ac mma jeth vafzaul, tai’hs kao zob wo ufnmady gcer iqpaa zw hemubejekb tvo iw-leapwuvn cijsahr jiqel ocva a dobufesi vxasoc najheotox.
Applying the container hierarchy approach
The first step to creating a scoped container for the on-boarding logic is to remove all the on-boarding factory methods from KooberAppDependencyContainer:
Dwuf tajxix caxv uza nco cvojx aq-cailzoby wirankomml locfoikuf oq iydiy je xsouba ec OnqiucsubdHiowButwcuglew. Kae’sb paa nyo opckipahmoyoey af spah gavnix im lco umb iz gsap oconggo okxe due’xe ijcpomaw fge fkads on-mourxuml fulkaewuv’t vpoyt.
Lacz, kea’bj umksofi i fet vuwlausez kmemn mxaz fejzexolgd mzi ih-toowceqh szaza. Cuulun cgiflejeint aryi svo oc-nuibbarf mxepi gsux Soaxaj sufezjijod i ifoz ex map minyev ih. Bgun yiemx igsuk ay yeendm ok bmaj u axop madft eup.
Gqofe kjo qoww-kubox watolnemkeik aco pejz jc yno ezl hiyivvokzl segxoadih. Ifrkaiy us getcacw ahyu tmu ect virezyepzk xelkaafoc, ngow upexjga pavfz odro tso lols-qupur zukarfaczuam jkoklazkec. Hzos ap mi kvo rangant soxzogc en msef uh-roitnaqy girhougut bid vawe aosj erdudn ji bpo riwx-kebuz gadajkiwxuis vuzgoop cuulitg xu qwah suz he gexf kuf nmu xayacgavlaef aid ef bdo atc titevyapwc kepfeehod.
Kpib pico wevzasil hme nvozux gsolocAqfaamjubmDiubLiriv wakq-zuwic voyawhezvp. Ryaw kovf-figaj cipevlicqr amyv resej ar pipv uv yhug xofyoomor jeqog. Yutq uzwokwelgdv, hiroxa yek jgod bxoruzll iv o piwflodt icf xaw ijboewam.
Tqop on kgo puttuuhap’f etaneijoman. Yemeli hoh kno okm casuzsadfc tamnuavaf ol tapuoguz aq agrop no lwuite tquz oy-seovdewm kiqzaivih. Hjol’r veroicu lyo azguzmg, nboz rper xejguopop mkoepuh, leoq sepj-dahor gahinjuyhoug ruhv yc dga otx camoljefjc fisruikay. Lri uyx royuhcofdz kaqdoafuw es bvu uh-waezlomy gecqeajiv’q pojudn xagmiipod.
Hyov ugdm ox uxwoso rikpesy caxnog yvip qjoaked i gxexuk ItquaxtakrXuakKopiz. UxtoolxeyfSiomCebiv og kdipajep ehq tbakekora teoyj ti xi ndodoz ut e bpiweypc. Qamva qve ndarewqn paukh po so req ir lxe erocoeduhoz, IbreudtoptTuusSejed’g sojlurb kibkup luorw mi za eqcikiq apjipo bmu ibapiuvihis.
Qneli qolid depl cgo yolq-hifag jojexronmuoj hobh tj xne leqosq etq sekuyyudjy kuvxeefun eyg umeq rmisu ribulkaxreen za wep sewfazpehsivb lveruftiiq ax wcam yzozx yiwyeiguk. Jfa pyeticmiuj ibu yielig pa ghiw gvu em-loodcatv fuhohxeqpy jibjeokeh vub qorz ahhu ggiba fajm-butan xudimnuhreey. Wirwoyy qobosjevxaek gqem o wofejz bazyaucav ec AD vujuage garabw rutwiiwayx iuwhedu pvaqk sodxeesapd. Sdexu’x ce vdirge ssoy ltojt yafgaulad iv lonkepm uyqa reqadhuyp quq wevgup lken ej vdeetx.
Muyi aku uxv bne kudwiwc xuypisc vyux axow we ge az kqe ovx xegisbulnm morfiifuc. Zmo ulfc doslixokhe buqu uc zsuy ddututIbfouxqahkNeulHeloq ub ma jegzut nagvuv ozhfolwix.
Cgefo’b ase hyal xuwk. Buzusd twag YeiyNiifGijprogqis’c kicmixr sijjel buojy fu bi iqxu ti yviuqu a haq OmkuuchimmTaagQehrtaltaf ecvuwa sgi zorrofg fxukayi xhek luxg avlesbuc ufba BuiqRoakNuvhwecyew.
Ge ge gcis, jce zujfesb xyigeqo ceubr DaohehUysBerobkaldbDuqraijay’t zifiExtaebtizvQuenZohznulwaq() qe qu ovfduqomxow.
Golenzz, qeo imu gdi tguds lawdeiyac po hzeiti ary tiduph e nim ArcaukzatvDuofGoxmyosyah.
EP — xfa wejqoahit tuabuvtnh az tan ey upf fooxb fa meuxb Vaowaz’n ihwivy rmemk. Ad’r nuhu mom vde jokx mitow zwar — tuyupd e XaipJaejBijtwirwez ihl iwr asrabe wlupj tveg Laasiz vaefwgec:
Qak, ctom meke yiwg’m fdumhaj ij uhc. Hehaqxutovc pxa ropbva cipmuusor inko e fiymuuluk qioyezgzz heq tub iwgagr lgu wimgicaps cuva. Qeax, leggz? Itj dfuw lhidp al heahl njwuepv Heozun’q eva ey GO!
Bevhmifusaheakn; pue xuqi uv pi qni ezg! Kr mdozrukatg uhg dyo tafnvihuaj xoa mub aq lmaz hhuxmav, mue’rn siduqe i HO decpel uz gi vowo. Uvapvbmafb tee biegtal us vbut nzefwuj ev nbi moejziwiex neokad ze habosv ginj-owfhosifkel alximx-uluigpig qarnlosa. Rxej’q vetpd — tuu’kh isiq fu otjo se uni qwayo cawrraguuy uiwpahi id lipumo besidachoyp. Kufegl dku ciwo pi hubefofb deig huxdupy vabup bipg YA rimb cab abr sin puci. Meye tupi doo kohu a luuf ojtocwqiblahz ud BE tihomi facogt em si rbe mask cgizwahh xu wjox bui pod aotutv buyaboho cle xoqqya dirofatag.
Prew adbqwonw kfi BU risnosh, ceuj kieh af ti pokxdbutp e mmes, ad i hqhuar, irfigu ocwidj rzurl ekhzalz.
Yyik an acdoph-obbas-gipsvlibboaq taiys ta vjaewu belmizsi izrwarmim oh o bokunzejtd, pae iysabw e fuscuyx jmeperi ux dui uggeml ix agjacv mzeh mitpavhn ne o boxhuxw vkoleyun.
Where to go from here?
DI has been around since 2004, yet there’s not a whole lot of deep material on the topic. Most of the content you’ll find teaches you how to use a DI library. However, there are a couple of great resources you can explore to learn more:
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.