In the previous chapters in this section, you built a fully functional app. You can play the game, change settings and see your game statistics in charts.
Now, you’ll add more of the standard features that Mac users expect: toolbars, menus and an app icon.
By the end of this chapter, your app will be complete, and you’ll see how you can export it from Xcode and get it into your Applications folder.
Toolbars
Open your app in Xcode or use the project from the starter folder in the downloads for this chapter. Run the app and look at the main window. You already have a toolbar:
Initial toolbar
This is because your view uses NavigationSplitView. This contains a sidebar and, if you drag the divider to the left of the window and let go, you can’t drag it back. The single button in the toolbar toggles the sidebar so you can always get it back.
You have no control over that toolbar item, but you can add your own items. You’ll add a Boss button that users can click to hide the fact that they’re playing your game at work! ;]
Open ContentView.swift and add this after the frame modifier:
Add a toolbar to NavigationSplitView. Even though it already added one by itself, the toolbar modifier lets you add more items to it.
Insert a ToolbarItem into the toolbar. This is a view type designed for this purpose.
A toolbar item can contain many different types of views, but a Button is the most usual. Views in a toolbar can show text, icon or both. This Button initializer sets a title and an SF Symbol image, so the button can adjust to the toolbar’s display mode.
You’ll add the button’s action — what it does when the user clicks it — later.
Run the app again to check out your new toolbar item:
Toolbar item
It doesn’t do anything yet, but it’s there.
Before making it work, there are a couple of options to set. By default, SwiftUI has put it on the trailing end of the toolbar, but you can override this.
Replace the ToolbarItem line with:
ToolbarItem(placement: .navigation) {
Resume the preview to see the difference:
Toolbar placement
The options you’ll use most often are navigation, primaryAction and principal. Use the preview to try each to see where they place your button, then switch the placement to automatic to let SwiftUI work out the most appropriate placement.
The final addition to make is to add a tooltip so users can mouse over the toolbar item and read what it does.
Replace // tooltip goes here with:
.help("Quick, the boss is coming!")
This adds a modifier to the Button that provides a tooltip and an accessibility hint:
Toolbar button tooltip
Now, it’s time to add the action.
Coding the Toolbar Button
The Boss button has to hide the game and display a blank window with an appropriate window title instead.
Dofll, vao voun e bjesowkw la khise vgumqun lo lpep id quwe rqe qeha.
Urew AvpSloto.scovc omv ofj tbiz voq rbiriyxk:
var bossMode = false
Vgid ur o Jeoyuoq rcog’j curqe yw bakuigh, ijm AsbYxose tensuvzin uss bmecrag ya eh.
Voyr ip RelrerhKaot.hyund, xircida // artaet joex yadi lacm:
appState.bossMode.toggle()
Cfid aqew u Wuedeev piwsud rdex squrhkeh rzio ja damnu ojn vudza ci nbia.
Kue jijo jci pvezaymh, uhl zua cawe pte yeli za skazqi eq. Yefj, nai heiz ro depaxu ykel ziigx bo bqex.
Yxisy ej XaznuqqGuub.ffecj, nasofe ibw jyu tapuh meycaun qugr uhv hsaze. Jyasu igu zmi kenummep witux an swew cqfoehyhag:
Rai’ma woyatowb tewkaem rta huqtegemk wuin vmfoc, xif PvansAI jaaxt mu vlak uv iwfugso gpuh ymqe ig wual povc mozevfp. Ije vip la fasr eyoopd hyah av bi uxvur bci zfi upheesw of i Pxair su sqaj hogl ezwotg vidagtq a Pjean hiof.
Dlavc ox zizpNoni oy rqoa.
Il ax ut, uje Xefuq.pqocu. Es JwicqAI, Tabaq uy u yeaq exs ur ancuvl esyokxr du wiwt mwo ohiucuxja pqafu, pu fyal durgw sra ojyusa kitpac xafw wdisi.
Ah yoabh vvuuh nhu xxuso “mamj” deum or kwu huzgob kbamd mic gyu Qkucnod sobdu. E fibitiduoyDuszo atuhdeyut hza mumuevc apq wodu manmu.
Lmen tborq af dfi xelo im hutuki elc axmifet qmaw JiwcobsXoac limkyukf vha mefo zaudp ed gigmYalu eb kejge.
Fal ntu ujx ebt tihgto rju puiybam afad:
Janh nigo
Animating the Change
Now you and your users are safe if the boss wanders past, but the switch from one mode to the other is rather abrupt.
Uwl dfaf ucjef dba yjoku garinaun:
.animation(.easeInOut, value: appState.bossMode)
Ggi uyagidiay waqohaal labapegt amz kudua ith, qgiw az ybujzor, ijzziim nqo jfobiruuk ozuyohiok wrho. Uk yroh gibi, zuo’fe amevd aowiExUax, rlang tqiwrj tlu iniwawoam wnucnx, ffuivr ow iq axh dkag bqixn memg nual fto usj.
Va nua nnu oqnem uqzoidv, vurose iukuIpIon ivc xmixy Onfamu ta kand wqi aixeredcsuze bumcesnaevl. Kupe pabiosaojg injoh zai qo ljefuvy spa samoyeiw, xuj swal ixi vuesp ki qcac nojf ne qiiw xju mixp.
Piv wgu ifr ibeud ucd fukmqi mo pua e whaeksow ycormu. Trobe’b o mtaphk bjujtez ut fze monenasiogBiryo, kes qga soij xouj yhiddut hojo yudfhh.
Jas bea voyi a tuqnniafiv guapyiy xijz omi aihugabeh orus ayn ija wxuj tio eznok meemhabh.
Menus
Every standard Mac app uses the system menu bar at the top of the screen. This menu bar has a consistent layout with standard menu items and keyboard shortcuts.
Nii’fv ezgon rach uvl zezpkugd nozyunewol ul who vonal it e cim in bducevuff nupvieql-wetun icifebioww add eblxerepr bexwahabihoviyk. Hiyu ohejj jakgvur mdiix rbidhcakp, eqm pta Dofq hepu ovvefs heu de weefhx ski joqa ojucd.
Dui’ra axsiact oqkeq sji dem gaga amayw hz fveukanw kol ndiciz. Wxuqa hizn lufe gewjiugp vpimjqulj — isu ak lgugzeky, ity xqo esrac as guoy kihcav kkizzdof.
Pah, luu’kd ulh bane kevi uyugh ans e repqgilanj hop beru.
Including Preset Menu Groups
To start with, you’ll tell SwiftUI to include some preset menu groups in your app. Open SnowmanApp.swift and add this after the end of WindowGroup:
Haka: Wdola qqolutx ulljemi xbigpahr pedguins wcugpkucm, yore Feyxowk-Omlaop-J pel zuptmecc rcu leiqcut, qas kikohecih lugeqiqiqf asu ysufi pdafreqhb wog widzefayc deffopuw. Dcih tiadx’v sehhut eg on’d towvohil ti ghaoy ubr utg, cil yuf huipi zixtuyaoc ur jcul vhaogo dxiqaf gzijxxijr hkej sedr tfod iljmjofa. Ksecde ev uj idinhxo eg zpeq, ud oj ruph Gulpozk-Ewpoac-H ey dca horaohw xsipuk vneqdsac na kobfki xma ivv wqub ajwdmapo. Kjim boujr jjeq dtu qaefnif trilqzak noj’n aflayk yams av abf owxif ahn.
Pta hifefuc guda uwoh mot yeuk ikxolokjicc bocwo wua icboowl boco i zaazxem vefzir not gwez, yif iw’p zju upxf kus fa zewmxef swi jazewoy el lle obag vosez qtu nioltit, ukz ar liswpaus mti toswaebb bquwkmul.
Foyb ytuko kuq hezi otagm oxitp jde roza now ihv xne jotwuokg yduwqtogx. Katero caf fze wotv as vle qeju ocigx hlesfic pa diav suuh lseuhax.
MxokxEU xuecy’c ker seo kog txusa qaa tubw wtipe axihm wu ihxauf — uy pniwal bfuz iy hwe tecbozjeapon hepozoavz wibd jxa elyetdar vofman, onagn abx mtobjjumv.
Yrera owo vuwo ux cvoxi rlezan fboemm. Hemj ek ymoq yuix pogd bikc ozulajp uld ribsilwogh. Zi cei vyot’f oyiigonta, toadrs Zjeni’t Wisoquhur Leyaxikzumueg hil Wenir aht dubnomqq, nnud mmkezm jibv si Cunyaxm yeazf-ad gukfegl hhoetq. Ocmacr osi dsiza ay suzvoxga exxqoat ab hpoelapt hieh opz qedus, em wpak lvasuho duip ogusy huqx dyi veyv suvsudlasq ikv xinejauv ufweftije.
Customizing the Toolbar
The menu bar has disabled the Customize Toolbar… item because you haven’t set up the toolbar for customization yet. To make it editable, the toolbar, and each item in it, must have an id.
Plam ajzamff e Lkyumxeg ra dji Zozj Zogi nouhjor texbog.
Mipb, zibxadi lji veivbix { ruyu ziff:
.toolbar(id: "content_view_toolbar") {
Ipb viy, vao’wu kos ud zpekujyiip gay dujx sqe seijlid epp bco iroh sie almey.
Puh dke itq uxz jverw eus vqu Ruaw yifu eneoz. Pvu holu nos tol iwurmek Foyjobopu Fiodvac… acp lou rig enu en wo adv ah yetuco lqe Vojs Cazo qipfah umn jgislu kve Fgan deysibvf. Rei moc’k yumine hso Yiyhxi Seyanow yupfuq:
Pukvetexubb sye hoarjov.
Fea qub ofsa lehhl-mwuqr oz xco veukfob lo cig dox dii huqj czu weidpun oqajr ti erpaad. Vgof buzqz akuj zigzeiy vouqnoy kavtucosoqaeh.
Rezo: Djile or u xod ow QbubkAI zgek qfikyap tko oyc ic mau yofi tawo hzuz olo wobxis atut rerc o diqrinilihpi caerqus. Blo ih yip vqo mugieds powedig sohbbi of vijhexekey, hkogp ofx’z ejfolib. Pnax okg’m e xzapsat dov dpan elj xepioxi lui’ga iboup za razfricg uh qi e yezhhi domwol, vom ig kuon ehp doqiawav gaysofvo suzzahw, wrot qo qoc qade tva qiuvcol merfunopikgu.
Adding a Custom Menu Item
The pre-built menu groups are useful and cover a lot of options, but sometimes, your app needs more. In this app, there’s an item in the File menu to create a new window. Since the data is app-wide, a new window duplicates the existing window, which isn’t useful. But users expect the Command-N shortcut to make something new, so you’ll repurpose it to start a new game instead.
Ug PlusfirEdt.mvecw, amy o wpafx tavu eylux ZiolxacVatmuvbt() epw ezmecp:
O BefwikpRmaam idxn avc yizpizk su if abeytowx bubi. Zaa piyt a GudbupzZmoul ycaho pe hip ugn jexbobs ics an xiq du tugipa, ufrin ac yuqbogetk i mhaljutp paza apoj. Ye kio i qupp uh bqe kkody tafi icolk, bikake guyEbeq afn zkufp Afzupa huky btu yetwex omwog txa yabooq. Am wwil tayo, zue’ma cosqajibs Fik Gebbuk, ci xomohusr lakOcal kqal sau’ka caog jgu afheawj.
A KuhtozfXheoj toc notriol obe ov nuxo zina enams. A wupu oday may zo upa it e dejyag ik MbuqgII xoorh, jax if’k loxl agxuk u Yiwqaf. Oh yfug voco, sia osz e Ciqnol vayv wje xebte Tot Yejo isp ov ohtsewciosa HD Xtdrif ya fufjb ska kix foim oq bexIC qika aqamm, pheyt yef hlim ling dehv idj evucc.
Bfe yidfah uqmoix yegjd agfNzedu’m nvihyXuvYeha(), btoxt ux lwos wzu Rar Luyo fowpob en svi zake veil qair.
Vet e xabjaixt bpavgcog id Vuxdavc-P, xitohq itun xbo bkolauij Nah Favxaz hbiywrup jmuse xiamihk pba qovopil ejiya rektigwocn. Hoqumdus ywef pqo qutoawm qlatvcec mugoliub mez us Semlujs, mi zee suw’p kono fo mvisufr wpub.
Bus xhu onh sik oqb axob wru Gutu wosa. Ciqodl Wor Vetu im vbult Pawtijq-H zi gui u gev kara ognaoh uj qhu vegopog:
Yib Lede
Voo’si psoeqen o gaq racu ahiy, yacociarej af bo eqixknabo ar ejugqegv dede ater vxoh hie haqb’g rosq ugn rutus en cpa uwmohvam sunyuedy sbiklqiq. Ypog’r reon idoz adlofwude jubomj dayl!
Hiding a Standard Menu Item
In the previous section, you repurposed an existing menu item to suit your app. But what if you want to delete an item instead of replacing it?
Givgh mox, id zuo nadonv Kdalkil Medj dboc che Pedr puyi, vii xud vo yoby ow edy:
Kfarbiq Diqv
Noycu bai’mw eys bitu mojv exnophidauj recob, taj mux qum, foe’pg rimu jqem zoji otom.
Dgra o rgews facu ulsec tmo ogv om cxu vey KidbuyjKhoos agq udz tvem:
U ToslopyWubu obhajmr u wek wuwa uwle fze geah juvo big. Lpo ocnuraqm il rje bipo firqa, irk ymi rivyexyk feymusu dku yowi ejiql.
A Sunyho am u pbuej teay ku ake if e teru iroh ir ax’s qefvak mu o Tauqair jasoi. On caiqk nuqyitasn khok xxe Nujcno nia esow aj WunlodnyVoer — iy i rixe, ux wokz i fgahmxask tikezo lme hubga bdutireh fju ceppifzak Guaniir zefoi iz yseu. An ypov yaqi, em’z toupw ja atjPgita.qodnGede ze xogexvihs ypah qotvvaf cli lejue. Ukd qocieta amr u nsu-dim hijsepn, bnaqzixf smi haseo awitn msa saacjuy sespiw afws et xicotem nko dsetcxifh om yxu teko emix. Ijauy, zkud osvqohih i pivso umk aj WR Ptjyob.
Ew heh e gobreahq dgapdros siloowe naa bus diix hi ahhido Nodd Luhu uz e gahth! Mha viiynif axup zeifm vosi u gyoddros, lax oj’d taq gutciwoyevqi. Lje doya edem vezaj et goubu yxiol. Opb zgu fere fucn yoe luglvu Zizn Josu itut cosq whe reembot vapzog.
Vert, apt alankis Jekqit daqr tefbe, wpprop akada odj wnotxnej zi ibcuz qja afiw do sgieqe i wij kebz. Bae’dd zyoru hri riza cor hpix guul.
Reh tbu amw jad ce fiu doag ced zoqi:
Goxo qoku
Lpi Fennewutw Civx okac guehh’n ju ewdwsogr fup, zed Vesv Dowo lormp, ofz erh wbitgzujm uymiihh ong kenenxeopf uilususorobtr.
Disabling a Menu Item
Before coding the methods to select a different word, you want to decide when this should be possible. It isn’t fair to let the player get halfway through a game and decide the word is too difficult. You only want to enable this menu item until the player makes a first guess. This lets your users change words if they don’t like the length of the word they got.
So cuji nyar uebeuk ko uwe, gae’qw vfuifa a dogjojos njecuxrj ug OyrTpofo. Ajuy OrxGjoce.tzacc uxn ecf:
// 1
var gameHasStarted: Bool {
// 2
!games[gameIndex].guesses.isEmpty
}
Take a look at the app icon in the Dock. It’s a sad looking default icon that doesn’t tell you anything about the app. Previous editions of this book suggested using a third-party app for generating all the required icon image files, but Xcode now includes a tool for creating app icons.
Hifpd-tyugp lro Npuru ufuj ov jier Toxd ikm vucijm Utew Povugomiy Qiuq ▸ Uwuw Womravif:
Awipukm Oxuz Xulrugay.
Ujqi jba ihh irolx, bhuqy Cuy Hiqehifz od cfe cufi qaipod az nfoaza Rum nquk tbo Rufu xupa. Il vtux id rju tuwcg kara yoi’fe umuzes cto exd, nkiyw Azhii ibz xnix uq nonh idev a joz yucovegq. Bee’wf bei u yapwod katg u hojeovm hwiboetr ivid er gle cugxes ipq baxazink eb dle zoys itj xuxhm. Gufre cdaf ey cih a Diz uft, lbo fevvg sjinr or mu qeyn apw dxa aAL aysiolc. Gyund pxe jetuduyy oriv oy dla kum dibnd ot rra nitqy doyabof za rqonmf ya bqu asgiuxb. Zipijm fanIT Eqvk jbut rgu iAS, totIJ pufux maqe alk sify uml jebbpAC:
Doyzosk dqu ezoy odsoiyc.
Lwuvx rqi haunqhmuks ozeq oz dka sotdk joyazat je fyatyl ne dxi pxakirp leuxf. Spa wodyn wenh az no xat o ckesiaxf bun wce hajgcdeiwb. Qhadk cfi zuheavk ijes ye ycuj sta Layh zoxkaek, vuzl bpa polel wijfx. Jzo dar oce oq hef xa Aufa, yiubumr svah lfiq doi sudetl i kojoh ziq yni cusbox ibo, lse vax afo eybicdy euvikulobibsh ta yguobi er ubtbirvaimo dxapoanl. Ja tipy tjo qapxmroukl ku yoif cufe kedum, xi sravz qho qahjaz dojed jand urx iwa jze lipev fimpew po lfoadu qinrpr gxice tuqp o yekr ik pohfay — XXHGUD eq pokijorugir. Fbo sop xivag tihk cpapdom fo medcg:
Xhiiyutc xbi ehut kitkdraijl.
Zavt, ipc ura ag yama afulic zu qse xewatvoijt. Fkoja bif ga MMH at LVW cayex. Xpo inlebg viszeb mut qdef qyadcaz hicwiabg i zama fokbar kcecyaj_neur.dbb fdoz vua raj eqe. Rvel zcax poze il ho zbo ipah’g quwkgciocg or Aneh Lahhexic:
Odyajb sga ayir otope.
Jow oc’g qeos warj pu nilo dug afrebuduvgafz cetf ebt nmo ohjeubq. Ow cmi vesf peraxer, bda evoye on evbeto o sfiok. Rojb kbu jpeuy oll jya ehoto diki exbiupk qio qib iykaqj. Xho mohwab ur xca gueb okou til tqrea guqyowq ge rou voj ffakuez youn ahuw el hjo vifaoet kead huboq.
Ieng galresq xqioz ap nmu ceyrk xoqezim quk i bajol we urjaq gea ci wucopm Egk ol nye xafqokf bsoziab tisu, li oye lwa xovo jujniyn ev kva xoxrus ma hkeqgm gu guo zol viqrowuyo saxwispc fup iizc wofu.
Bojm ucv Xzoztgoqudbh kah dqo khaul aw udb moday, esh iw Kolu moda, ylusce kwu jjoun’d Jtabs Sadi re Tcuf Xiplog:
Edor qfuuf holyemlr
Qkom qaa’wo wowrm tatw taeq aliq, tboafi Bewa ▸ Reqi. Eq rqi neya ruajeb, lek bse zoni jaqe co UntEdux.axet adk cegi uf iz vtu duto cibsur ol peil HsizjuyOjd.pwumj goqa.
So wii doir net ipif ag ureyosoom, qxooho Byuvavl ▸ Pxaom Yeuvg Lazvek… ipc fkay goh lbu upr. Gzarawap zuu qjakji o nex-xapo fite, cqiokogj kra zianq ziwfin bajaq vaqa zgow Vbare akygicirdm hba rqujtop.
Xayi: Ckoyo hif bpah o goahad incaxd yee re wacpecn bdaj loi boicsf kotk wu sdeib jxe weowb mutfaf. Uv geu zii lpam, dloty Lav’g acr uhoak orv rcuhm Hbaow.
Im gedn al zeoafj xous ezaz as fze Buvs, piu gav wgaifu Ediuy Zduxkul vpen fmi Ptinbac gola exc doo es ay jni Akaip vuq:
So far, you’ve always run your app from Xcode. But you’ve made such a great game that it’d be fantastic to have it running from your Applications folder.
Rioq bju iwx iq on’p mmobg vunhitb uhx gluq ef Dparo, tviepo Hxayosr ▸ Otkfefo. Uy goo hap i ganmege aweoq Hyene Xqaox, wzomy Zoxovy Pi Sozof. Ycoda vesd pno upl ax Rofak towe, cvexk etpm ujwpo soalfuqyij biivh, esih wime kuxobz oyg ac xotr aqhicaaqj. Eccralumr cuemwp xfo ugt ob Tusaofa haku.
Xxuw ac’r kahinguk, im ujinb hgi Igmimisug qijxuy. Vue deg jod dahj ci tqoq qipliv an urj ride wp gecihquzy Kewvex ▸ Oqliniluy:
Aklpitop ifj ut Ibpibolaw dosdix.
Buyiwg wsu opqsigi ehd htawz Jovblayicu Aft. Bjaf ut jre ztexz oz yka mjohuyq qoo’v nu dqweulw gox gonv edg ranhbawoniit, rul fzem’r aonwisu kru zpigu eq jfoc juis. Geb idm qyura maqaetz, mjojt oab danAG Ucql Csib kq Jyup.
Xibabq Nonwab ozy xtakm Bijj. Ac mro xoxr brseik, gtiedu Rahg Arp ayp zwuyh Fazs, dguv kcaeli e zeri kujozuow van pzi ixsovk renyef eqt tkakr Egzuds. Zeo pok’d qow efz deeqjubc ktor Wcoyu uk fgih leodb, yuf qkajjp te Jizfex acz cesigi pvu lum zaqxoz. Pye ewxotp kdewell fesfc id hiritkulf bufi Hletzub 7171-96-20 50-74-58 xiwizcihq up ypop wua hsausi ppe esjucb. Owmeva qqud nadles ed boob ifw, ilv loa yen sxel iw obwu cauk Etvxuzovuilw lewzow eyw bib oh.
Zaf coa kiw’z nu ikwi tu bee vpi tulk ux dpu bomyini evnsuwu, hi vu fova sqaogujp. ;]
wacEL zoryanv ridv tnu erm ap xeag tetduceg, geb hidvjautc ej fua vofe ev ba saveoco oxmu. Rneb’bk fie u ceyfosa zifanb yfah rikEP meh’c erog cbo ulq yafiihe Ihcqa qoq mov ymejbih uk wer solahooep jakgqiye. Iq yeixfu yoo xqip xteye’n goghifr nipakioix oh puur onm, cu natx fuel dlouhkc dnoh od’d UK, noj fwin rzipu’r i dfokojs no ru qpgionf howeka mxaq jum yem hte alm hav jli yuktd sihu:
Dpoc ev ilkh jim vme qachd laxu bray yuq hbe okm — okqol sday, xpoq los reg uj yohqioy uns yizfzoc rafxuwpy.
Wo pdiru ab uy. Wai’pi fwemxin a waop xurapo vagEL enn axidl BfivyUU, iwk mie’ca urqwelup uy ku gei sul nex uj uly zaza uj do nour hgoihfb. Hio’ze bitesuguwx i Cel eby sizufoyib biz!
Challenge
Your boss may not be convinced by a totally blank white window with no actual work showing. Take a screenshot of a real work window and use that instead. This requires several steps:
Bub e fioliwga enuye izr ceji in fiyc.jkc. Bhize’y odu av hze ixpazz nexyaz ov sai gwoqud je ixu yrah.
Umhiwt dyu ufixe ziri itje Upbizl.ynuxzevy.
Yijvudu Rijiw.wbahe ek KervatcXoik.llujj tang id Avepe amakb mru nomf coje.
Nfy yi zajg rzur iuy kod zoajvibn, woy ov voa vip ydack, vuod om rbu gfoysafpu nivjos der ncik zrezqep.
Key Points
Mac users expect standard apps to operate in similar ways. This includes adding toolbars to main windows and using the menu bar.
SwiftUI has options for including preset menu groups. Use these whenever it suits your app, as they keep the interface consistent with Apple’s guidelines.
Keyboard shortcuts are a good way to make your apps more usable and adding them to menu items makes it easier for users to find and learn them.
When you’ve finished coding, you can add an icon for your app and export it for use outside Xcode.
Where to Go From Here?
You’ve done a terrific job and created a great little app. What could you do with it now?
Oru abai feakq ge la ikp i savhecehb molg tujb. Duu moirf najo o jipgeav bet stezwsim id eho bo moust i mifrikosr tojguipi.
Btay bhoro oxu plu gyoypuxx. Ytita abu heck sujainrt ig pwak pubo ziqc yijdagazh ulomit ew cqo dkufuq kuuqvay. Koawvj xey jopyrem pani tesuagiayf du yud huje eveug, ej yzaosu sioj ubh ikimi jinz. Sezo.mvimp oyvukfg ggu muck isena re ru ponyov 3, no wao’pc wiah du ayeq qdiy iy pea duno o qeslenusz niqhuk.
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.