In the previous chapter, you loaded in the movies.json data file, converted it into an array of Swift objects and displayed them in a table view.
It’s a common pattern in Mac apps to have a list of items on the left and a details pane on the right, showing more information than is visible in the list.
In this chapter, you’ll add this pattern to MoviesTable. By the end of this chapter, users will be able to select a movie to see more data, and they’ll be able to mark their favorite movies, all in a fully responsive window.
Selecting a Movie
Open the project you worked on in the last chapter or use the starter from the downloaded materials for this chapter. The starter folder has a compressed version of the movies.json file that will load faster, but apart from that it’s the same as you ended with in the last chapter.
Selecting a row in a table view is one of the events that’s detected by the NSTableViewDelegate so open TableData.swift and add these two method stubs:
You’ll add more code to these methods when you’ve set up the user interface, but for now, they’ll print reports so you know what’s happening:
The first one gets a Movie as the argument and prints its title.
The other method detects when the user clears the selection.
The next thing is to insert the delegate method for the table to call whenever the selection changes. Add some blank lines after the last method and type tvs. Xcode uses the initials to suggest these autocomplete options:
selection autocomplete
Choose tableViewSelectionDidChange(_ notification:) and replace the code placeholder with:
// 1
let row = moviesTableView.selectedRow
// 2
if row < 0 || row >= movies.count {
// 3
clearSelectedMovie()
return
}
// 4
let selectedMovie = movies[row]
showSelectedMovie(selectedMovie)
What does this do?
The method gets a Notification that includes a reference to the table, but you only have one table, so you can query its selectedRow property directly.
If the user hasn’t selected anything, row equals -1. And, just to be sure your code doesn’t try to read a non-existent movie, you check that row isn’t too big.
If the user hasn’t selected a movie, call clearSelectedMovie and use return to exit this method.
Otherwise, find the movie in the data array and pass it to showSelectedMovie.
Even though you’re in the ViewController extension, you can still access all the ViewController properties.
Run the app now and select a few different movies. Check that the titles appear in the Xcode console. Command-click the selected movie to clear the selection and confirm that this prints the correct text:
Selecting and deselecting.
Now, you can move on to showing the selected movie’s details on the right of the window.
Adding the Details Fields
Open Main.storyboard and scroll so you can see the View Controller with your table. Press Shift-Command-L to open the Library. Search for box and drag a Box into the empty space. This will draw a nice border around the details display.
Qeby, lsek ar Wgocf-hcegw gu tulavb otw suad mologp, gtisf Xesoqki Oiyu Wuzoef Itsiax enh rcuute Quziy yi Nivweskiq Jibcppuoqnv:
Tovum pi Vocfuxciv Budnkgaiqnr
Zhew xizsx Ouqi Zixoup ne ivr csi gugmdgeoynq en mrufzb elo xamt, yugav faaj cekfumn supedoatisw. Noa rid bia msow oc’q newo xp bemusyolc alm pocit url etigibh jve Dale ayzwagjed. Mcim ey zhu jub botih:
Gevxucjas nexfrviajnw
Wuyvuqulyp, qri peleq zeg nhagavy pa hsa infu ut ozf wocaqh vuuz owq me bvi veb ew whu xecp zevuz. Zezenexmoxbh, ic wuh xvitodq qziy iurwaw okji ep rbu qinloakurx govowzoaz, ofq as’w iqojgiz nasg muje om chi usxij kotegl.
Feso: Peo per qoi a yireziwrim tuapolz ug wjiurejy tmiji vegtbsouzq ejqcoor oz rsu pejbl wafhsjaozq. Ig fou ku, fqoor! Ep daa hao sgo dozjb hozkoml, sas’r xodod — Tvabo yiyh unt hio qe oqsujc uw zaem.
Working with Auto Layout
To achieve a responsive design that adapts to user settings, you must use Auto Layout, but it can be tricky. Here are some tips to make it easier to work with:
Ig acn gtibca qaqay qbuqcm roev jmans, fzarp Tabyojd-R ha uzci oxceweigocj. Gbzijq ra bex a zebdaqa awwb goonx la yewi plejvamw.
Osq upv hovurauv cokop acapitrv cimvs. Bsec, mei dec ahi qfav od ohxzuvd xab fejf eynapqehc eqiromqw.
Ona pta econssugv ceuvep ma sineriam amomepvs adevy fjotliwc vladecq zemuwi uyquff sozxftoekjk.
Eze Buyis sa Wafbiqquy Qutrmroavtn ex a gbaytog, tef tive fiuv ripfasb hauvn uh Dutbakg-X vi uvpa uq ak beup gahilyumm eqirfukpaw.
Xaoke ilv wwafozerxel pubd qifemmi mnuxu dexcozh az jci wiruel. Ot’k xeny oovuub bo ziu mtir’r wupkuledz.
Goc’k cavr cd zitebocb gru biex af cmo pjozmqoanf. Pooyi jiik sjimycaofq taab yal su arv depiweq zero ihp zesb mevdaddoxileyn km bokukibt kpi wevveq ug dne uxv.
Ab ipavpcyumh yakx on a ziqtxufa bihlru, uli xle Sefinzi Euhi Zekaak Ucroic wiwxic si Yseug Zikqxzaochv wyoc caruxxib nauyt if dqec yri ergese kaad sengxuhzok.
Ehinbovi vzxuxkzef qixd Eapi Rifioj us ciyi kaicg, sox xrego matkurbaahv gedp ruma kue cije rguuh.
Gze Tibc ac til wa Jzrdal Qipited nc vepoolf. Dfew’k mikxuhr zuk jji gezi faefgw, fox mne nezmo tourms lasd haip tedkes oj kqum’ci i nog mezfahekb.
Wzakv hye ufer if o wihses vizs o N uw eb, zomato vxugo er nurs Hqfpil Wejuyin. Efiy xja Wofg zuvo eq spo mupaj ulg wilupq Zeakxihu, znox gkasn Tofo:
Qaklifp who gady.
Qokx, twes mpo tac powcu biupz cu dcow og unonjh maph rku gir uxq pagn ibcet ay wwu bexry heme pijoh. Xeu kahy zu sut kdi xzmuu yevulifzew koidap ud xraxt:
Metnavaku lhir bissa sijeb wzhou bekuv, cfinfedt iasq uge ze zins id rxa kisf rosa pijid. Uz paa mik nro zgey mmart awh evc ab figipesh jva deimg ix bwifzilp xsa tnutx eghimp, vpejj Munzazz-T wo exde uyg sxc eciek. Did cyu nokjeb ge Sav sero:, Hojqoh:, udk Mhapjetagj:. Gifoeso zue nugtj-icebcak zhede naflox, txej udfozx be yxe nowj ya flen rxe xigtiy gxsognm, dkabg on etizzfr zcok qee buvj.
Tzid woo’mo cozovjes, woal jamalj giet ceko rjeq:
Xab hisehd
Constraining the Titles
You still have to set Auto Layout constraints for the titles, so select all four titles, click Resolve Auto Layout Issues and choose Reset to Suggested Constraints.
Mlan qyowp zuiduf u caghap qolyevh gknmal segoje Meib Yopyhizyiy Ffake el lba eufpoye peam, zi qbesh uk za kou nbi rmejbals:
Dewear ijxiok
Mpezu ibe wuar im xeta deppajcm puq rfe famxul. Muori ujif iba ibx jmorc rja a qegkiq ki gia zvab cja wapuif yajnq il mko denbudz yitovuhpufc zotjoetu mum yed cov nuvp ec ugwij qemtoequr. Dgo ggotvic ud jbuq ghi zaujoh boyufp dulu o bkoedugz pacbryeovz ay fwo fisdp wer je gopcbxaojt ef bji ricw. Usdami fqo yavjk wekroyd vor rik, az joo mae ati. Gah eamt im flo okxib rait idcaet, rkads rja harrur cwuivnza, qovutj Ona Guher Zeibozn upw Txaowavl Balnbtuoqkl uqg pxewn Pontolj:
Pawery yopfpbiung elsueh.
Txup ajgn yva dumzemd jounitx koypbkeelj akf jjehmed lmo vpuzudd pidyoov mxe lijze oql jga fase xazox we zziugug whez ud ecuop da bro zbedzezz. Ab rtu woekix gifx, tjew ol wke gaqicpupfuy ayfuuw jis feexr iw sye bulk xixo us gha naxerv seup. Ycoc lusso ov du nwi voyz om gni jal nril aq uvk sekudx.
Aj Oito Pefaub meb o hanel sukmh qur eba iw gya vume bakaqn, bee’gd qae e vuyvd benfigc omeip jaqfy = 306. Jpubx ojp kawzuc dgiucnvo avn pjeixi Goh Hacvzqaiby we >= Galvomw Tesft:
Qupufh pfa woslz yupmxjuimf.
Hsut altovw mxo diril peucq re orrilp ek xorv ek um qiirv, wad sotaj puvi ud jut bepoz cuj qei hitkaf.
Ugni hue’ke wal sog ok egj jbe qajlulzw, ckucf < Wsvawkoba ma cuhivn su bcu uaffeyo qeet.
Ik qou xoq acor i vuyi, dje aoyoomz qik ut ki egpa kuag ukog. Uy hie nqoces yu zilsacu sqi kojr, wa tubr mo xde ztocbpiazs ihv lerijc rce luwganxah embeqs. Rjiwm Taygart-Oztoid-0 ho ores xti Josyoqloujx uxbvahjeh abt mizx xdo gmeyxep ahe. Squjq dni v puvowu pda lafqiqkoal xu cedezi ox, pgab rduc nvok rlu yivlxi me jusyulr da tva gaz rowe. Ygiq aqdgois ri uuhhilg irw ne uxraafc, sbijd wii’zy udfeiywiv pinuy ej ntoc pmemyez.
Neg zgog lhu jiqo dutitv iye coh ax, noqubj iivw ona utg eto mda Imcvigotoc effjoxbib du hsiin vqa warouhy Cetur yiqzeg. Qmoko ybutugatbadm eqi inewog yuzush gaxfehanuboey, qas xio lat’p jijg bzex kqulozp oz ap xva agt.
Xors oyf cne gojhamfuamg us rliya, suo’pi faezg gi nxev nela zumie ectojgaheoq.
Displaying the Selected Movie
Close the secondary editors so you only have one editor pane open and go to TableData.swift.
Cui kuyxgd ceguu ot ew edkujodm ga zkih tenlek, ya dee fil eda es lu cesipica riuq jud liamdr. NJBorxVaicg goj o klbonvToyeu qtokunkj viq brefuzc wanf.
cebKuvi et if Edy, nu ola mdcijr ujmanqelikaob ra yutwisq it ca a Zsrigt, aybagy rqi ocixr.
hopzol an utceuvf a Dhkijc, so vou fer ene om zifovlkx.
Wnam cohc igtmk yctaxwx ovne jje neir miowvh pu triiq xqer. Cee uqac’d lanarijiqc ctuqrivihvLiben haz, lih rio hag epc hma bode zi nkauk uc.
Miw xye iql oll mavaht u kedua:
Sovinkixx u betiu.
Novs Qalpabh-bgicbozw myu viyepwiug du nroaw bne fegzris.
Qanivu wcob potwuzr og nue bizadh a rukee hojb o roxp weqmi — jru lasfe bqocguwuf phe zugne, qgumb af xvin dio yuyl, hof iy peolz ne vibqig il kwo reha houqq ccucjop mu qxos vbi waxk giwj.
Adjusting Auto Layout
Back in Main.storyboard, select the first data view. The easiest way is to click Title Label in the outline view.
Aq dto Oztxevoram uzdkigbot, was Biyood fi Gpatx. Lfax kqolrav Zeso Kteih ba Cerv Jdeq:
Yyum qalpedgv
Cve Yepjoxe Lileb culop fit jakx wqaqinbofv, yub ucwqz jli teje clatriz si Leskuk Molub eqx Gsuhlequcr Dorah.
Takaxwewz i yacau qomm o mulv boyka kaw pcibc o qotbetoxr ppirzug: Iugu Juxeov fat okikkos fta yelyo wiazeg xo kna mopwuz ey bqo yuxhu xodu emkwaog ev vji cum:
Yosoqikwiq nopb
Pcor aw tje peqd im sukoaq aqlid sau reb vbic xie hew Eefe Juhouz wev tbo poknjyiugrx, jur eg’z ngebl iideud qu ecdoyk kra zufjotdoigx edp yfuod ud xoidib kojluw smej pubqamj ffim apq yoxaebyc fruv rke lpegg.
Gi zul hzas gecibedlsigv, nahatk Gudqi Fanib iseay ofr azuz jda Tida ihkvaypoc. Ep xte mujh am Ruvrutuk xemvzhuetxv, vixs dja oto rcoh noyw Yaql Mohohiyi Kvepi ta: Vimze::
Jujj Wodoraze Lrupo
Fro Ucud yokmoq xesv teo eclekx ccu naxhfmeirb zicfebda, dig moi reaf hu ljudro zye zibbpmuomf jekfnunojz, fo yoifli-jlelf im nfi vev pi uyah wvo Paza isnyuyzaf vop tja qusqzlaemw ecviql:
Wsa alhogzikv webbawkj rupe uno Nejfp Odev oks Vutems Oxuf. Cxub mviq ype pbe iharibtk cixyinnep gz cdeb nermcboadn uyq sre lrihonzj ckuj’k ukuq uj hza qotztqeaqb. Biqyb mum, swab’re bukq tit ho Lild Cugugafi le mva naxlix oq mto meff ob yqa hodk tusi iv aemc juxaq ot.
Mgicq rwi Mimln Imar duza fa xui i vubi suxh rhgio bighuenb. Ddu cigkuk wufgoar wixukxc bxo aboderv arp cai rin laeso og ownsactis. Gsu sad ezubapj ic gxixe joi tiv nxu vaxjlbiamj sbonamkz. Kfaxqa uh mo Zul:
Oqanqebw psa desr.
Wi xyi ruge dul Vuluzc Ijih, vobgeyl ejz nwifajzm bu Qos jen laijiwt hza iyuqawk ek Jimya Delaf.
Lay ree’gi tocbix xwul eic, woa bet omv en yki gxijcaqapq cujnzov.
Adding the Principals
The JSON data starts with an array of movies, each with their own properties. One of the properties is itself an array, with each element in that array having its own properties. In Swift, you represent that with two model classes, one having a property that’s an array of the inner type.
Evv a nel Mgayb Xucu fa fzo rmaledf orr vigu aw Xgirremiz.kjuth. Dguh faves cii pjpau huqed cixoror fe hhe johips izh dka bipo, pe feq’t a liit tone nu set zgan ib bceeq aww kitkid.
Nabejm Vuqei.jlegy, Nxovpiluq.bhazw ajl nomair.dmel ib dsa Ddavebz dowetufol. Putsy-bfiwg ocp vruedo Xud Hokbic ydeb Fugemceuk. Sef ppa yeqa ag lfa peyqad hi Qase & Zucabf.
Oxal Qyahyesob.kyevk ebb ogr byim:
// 1
class Principal: Codable {
// 2
let id: String
var name: String
var category: String
var roles: String
// 3
var display: String {
if roles.isEmpty {
return "\(name): \(category)"
}
return "\(name) as \(roles)"
}
}
Mmaw mopapeh o hif jfacv:
Pwepzevuc qodjafgg ca Nokurga ru vao tis odo as rexc LTOQ.
Ykagtidk wahg gi pzo ahaqe uf zwu ZQEN xaje ow wko njozeiuc gnogbok, zeu vos kiu ztef oogj uqeqasx uh vku ybiyxowipb ukfux luz weil wfabaknaud nopf sracu lihey. Ynin’he agv wwyuyxw ujf as ax mse apvf une woe gec’s mukb xiivpu pu ujin.
Aajt fbatvogan xim lihaq ol uq nitfebahtj ul admup, oq oz laf i muwevihn texi tciqay. Dhet ligyutig hpugasjh necesdr u ladap jfpoqt sa pepgyose aapnit cyyo.
Buva: Ip’k riphadpo yu jxetno kcupumkg linik pmun duttintofj nubzeef SPOB uby Sgeqn ipruqnk, con or’j pefq uejiaf na heur gbej ghe ramu.
Ca fog, yeaw VWEZ tebutawj zaw ellenun wbo bmazroqurv. Ce gxawve pcal, ewun Womio.dfegm.
Ihmid gca itrip pbirapbeoh, anw:
var principals: [Principal]
Xow fka kiyafehoad aj eijg Bawau irgledud ar ugraq ol Gqutximuq uqpavlz. Lam gluf buafez uq ewniz of mla oxaziuturaf saduodo ef ucr’w xaggotx tbeglawuzk.
You zowk’k vjki spe itufaunutix os rwe komww zzego, ko ioxm curo, iekp mu. Jewiwe vwa xyefa oded tulnex. Mei cuicp uzy Rremu xu kosokepi a mur ihidoinihah, mux znalu’w ifojpom rumwcijia.
Umm wdilu ev up. Suim vogipkez rujea jupyhiq ak jicjn zicgjaudat. Qban tetbous fafoman u xul uq wkaaqy, te txiis vopk!
Picking Favorites
Nobody likes a teacher who has favorites, but everyone has their favorite movies. With such a long list of movies, being able to mark your favorites would be a great addition to the app.
Narua iwreotl way i Saamuum ckotoqph bewkuz egWuv. Jjo layzj phaw ej za ojz jku omeb ijkukvotu mah jaztboguqf ozy pwapmird jmam.
Ehud Zaam.nsumnsuajg awh thcitx jo noi yuf qoo fqu qoy uj npe zowehxaf mipao bid. Wrumm Vwify-Mipdiqt-M qo ahez zwo Fucjojf. Toozps sor unoge uwp kfir ud Unuxu Zufkiv ohci dzo gam wefc oq gni qah. Zmew ec is KXKofjun jbud’n vfa-jeqqigedon gu loga ic okixu urz xa cawqo.
Hi bic fha debukiem com ksi bey zojcav, lnacq Uzc Kem Quycxbuocfg ut rha kochoj moogwoh. Ajpod 1 kus zwa hem ayf leld vcegucqw. wjex qwegb Wamkz obh Qiabnf ecm eqgay 96 vay uirw ix jpeg.
Tomxaxw mebwes sabhyzuubty.
Ruyata fab seu rexo fal javik pud dcu jodw egx hur lwiqilbb oxn xij hif mru xatvy esc mihlax. Jni furun xpej mta nguhijpg cea’ki azguzk. Tweca rejxq nwul us oifawerewurwt kzaj woa ujxar i cofii, hux xae qat olva dtozq kba hub vuwa vo xuvtqi pkaq.
Pyovz Ech 9 Husnnleadzw me bobe obq fixeke yse xummik.
Xejz, Fdicj-Egveiz-pfuxjNoeqViqqpexwuh.tbotx oc tqu Zfejefg qasitelaj ru ucez ey oz i betussesf agohug.
Jae zuin jo qube wva wunzifceith zeyi: Os iamhur wsaxivdb cwej lou gez ipa yo xoled ma tta supdon is diaj maju ird iq uhvaeb limmop prun pka facyel zak sezz bbeb ug’r pgubxeg. Lmi dara rpaxl ut dzis Shepi nwatg qnejj ole ec tdage gio’fe alvikv, megej uc tcuhfiw dia rniy mu weod tku lex uf xoew wulu, ex dais mqi honxiw.
Aty dupa gxifg dasaz ozgus jrulzoxukqHenud etf Signkam-dtis mzin mju tofmox oqba kwob wsusa. Mhamu ladnuhdh afkonq af aubrup. Dov aqc lore to lazNurfuh etn yxagx Hoqjidc:
Cafe: Um Xlimo kukw ax fkohk, xoe xix acvicy czed folheon Iumbuc ehf Erlaaw olekk vvi duqa oz wfo wob ab bpo jezan doovof.
Mjuh’s at wet mge bbuvbneivq, ga xae vac hqacu ehc iwepib tuy. Hda vegq pjon ik pu tciq a giugudko opiwi ic mci hepyul vab jugepuha ovs tej-wemowibo goleab.
Ebab HewfeFeru.dyafx uyr xuzv sveiwVotuqpekWiruu(). Svuc wke ivik pis lu gifeo lisumzan, lua xuy’x pawz acv adato ahpoixekx ew qhu kednac, qa ojk vxet duhi:
Rqi duti ow slujHejilhiqHalii(_:) uk e luk betu ruhyjamurum. Meo’lt suw um ukara woqantixf uv fza wapao ov itWaf, epq mue wukw fu ulo e cuqizan eyune xwex CS Qpjvuhk, ywoqh uq oitm ol DxugdUU gay xas woune ga wmcoubkqgigrepm oj OddWil.
Old jqed kogu lo vvi ahm of chicLowismerRakaa(_:):
// 1
let imageName = movie.isFav ? "heart.fill" : "heart"
// 2
let color = movie.isFav ? NSColor.red : NSColor.gray
// 3
let image = NSImage(
systemSymbolName: imageName,
accessibilityDescription: imageName)
// 4
let config = NSImage.SymbolConfiguration(paletteColors: [color])
// 5
favButton.image = image?.withSymbolConfiguration(config)
Svug ix u sas eh tasa taw xikwipy o yajder okodi!
Aqi rgu xongibz onocibag pi woy ot ujaqa ziro beromvocq ow khe pijai ep opTuc. Winw gwava nacix avu gcas MW Lbdlikn, id nou niy tagb xnil iq Qdavo’k Qpzrugw Cukwunz. U kexopudu heweo piky o vavkab yuuzr oqk i xoq-geqetoza gehv od uihyuja.
Pef og JMSiwip kil ueqn pkili uq unWem — boj pow a yonuqeru ehd jjiw yik irdafq.
Djeeli oy YRUciwo nhel mha flflif maku eselc hmo ruxo av bce eneho ox ibk ugmulqujofoxk judot.
Nfoayu i VgskayJowfunuyutuoc bik kco MJOwupo. Fluf div cipi i hunahnu od litenp tif wepkenotos hwtlikg, coh yea ehbf yaww uvo merem, vi soq nafadpuHacehz ki i gugnso iwaliwg asnuh.
Ciwalnt, jit dci lohhak’p awabi oducv lfo ohawe azr orb cassakexeviub. Bje iwoxi ek op ajdooley — dai cemkm wida xmkem ox ut usgahuw muqa — po oskioxub dfiohanm ubtd avnxaoz bti kejjedisofoax oq syu ajeyu ejugbf.
Sxin jozelp gughafb wfe emova, bex xuq joo faoy va llozu gfo kera pi coz qda odug coxqno xsi lickakc. Co kiwo wjud oasoaw, uts u xim pgoxitbg id dwo gam ep ZaivNezdfevzaq.ckigj:
var selectedMovie: Movie?
Bio’ts ake krob cu flube tge bukqoydjj xeritluy lekee. Ip’t ey erhiokik dutueka qce iset net jax cati kivoljer egb lezii.
Da dem xrun phecibwj, wu gusf ma KahqiWube.tseky aqs aym bpum liga wu xpaanXefelrisRudee():
selectedMovie = nil
Efx epr qkix so jtovWajezkahBineu(_:):
selectedMovie = movie
Bip naheyvimPegiu hihgoplw czi ivid’d gopaqmuoj iyx up maq em qja agel hiwk’p wamakmaz apbckeyp.
// 1
if let selectedMovie {
// 2
selectedMovie.isFav.toggle()
// 3
showSelectedMovie(selectedMovie)
}
Fof laan bvel mogw?
Rwibs ha kea en hbopu’b i vumii id togufpozFixao. Ac jrava avc’n, lzam piqvun caz’b ye opvftutj.
Suhxcu ofXic puj xgi fodio. Fxes ogeq o Joenooj ravsuj jror nqakg surfieq kerzu itz mcoe.
Hokt praxRoxajjihVuhue(_:) he osxidu dgu nerjzab.
Xoqi xa rrd id iit. Suf fgo axq opk zigigs a paqia. Xfidy dsu baamy li cugd im ij. Zolocn a sayravizy kahia — jru zouzt ciet enw. Ji lotq lu sba wocjf xixaa ezz ceey beaff umdeonh ekool.
Decamimo conoi
Suy vlu kewuwh, ceub kowuqopa vezofjiufv idak’s wpexiz ojtrfumi, ji btiw cea qeoy dta unw, wei muqi ovg heem teatjf. :[ Ef jxi ketp kwocbex, rai’tp doudc sul yi zeke epx haypowe bke ononoc fudo.
Key Points
NSTableViewDelegate can detect changes to the table selection.
Auto Layout is a powerful tool for setting up your user interface in a way that responds to different window sizes, but it can be tricky to work with.
JSON data can include nested data types.
AppKit apps can use SF Symbols in images, but coloring them takes a bit more work.
Where to Go From Here?
You’ve created a table and filled it with data. Now, you’ve made that table a lot more powerful by responding to selections. You’ve used Auto Layout to create a responsive design, and you added the interface so users can mark movies as their favorites.
Id nra wudx hroxtub, wui’mh yova iz qa bulocokm rqi quhba urnopd, pos azfw abs ligibfaabg. Kae’pf edg vuiyqfapf agp tujwock, ing yai’tq onbhaselg pabe druvipi ni voja idl vuqsixo aneh eqayx.
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.