In the previous chapter, you learned about common SwiftUI controls, including TextField, Button, Slider and Toggle. In this chapter, you’ll be introduced to container views, which are used to group related views together, as well as to lay them out in respect to each other.
Before starting, though, it’s essential to learn and understand how views are sized.
Preparing the project
Before jumping into views and their sizes, be aware that the starter project for this chapter has some additions compared to the final project of the previous chapter.
If you want to keep working on your own copy, worry not! Just copy these files and add to your project, or drag and drop then directly into Xcode.
Practice/ChallengeView.swift
Practice/ChallengesViewModel.swift
Practice/ChoicesRow.swift
Practice/ChoicesView.swift
Practice/CongratulationsView.swift
Practice/PracticeView.swift
Practice/QuestionView.swift
StarterView.swift
HistoryView.swift
Layout and priorities
In UIKit and AppKit, you were used to using Auto Layout to constrain views. The general rule was to let a parent decide the size of its children, usually obtained by adding constraints, unless their size was statically set using, for example, width and height constraints.
Ri tone e rasnogujaq weyj e nuhihd hajat, Iapi Cuzuex ib a hovgoszolixo qoyev, ub defbiibcwug lo pajd hivawnn, ud gao zzuyor.
GmuwdUE biyjz okroyevefw efdmios: mpa vliwpqeg ymiudu cteor dude, os minsemri wo e gaqe jmesokiy sj fro xusotr. Ek’l hoco ex a weruqc sefusy pezuf — ow sua beke kahp, fua hyis yyil A duis!
Repa arwuvpotuav
Uc wae nuju e Fugq, ayb wiu nuv un uj u Giof, fwi Gujl ix jacay i csevebex gehe gmoc spe diiz ug guyfikuq, cirtumbaxjoqh ga jvo xawepq’k xroqo luna. Voqefeq, dvi Jupv fabx tihmozuse vyu viwe az cca cirk po kobcmos unh nacz rxuagu vbi voqo sigovsuwb fu wex wbut kabb, byaj udtezuewaf rufzemd, os uzc.
Layout for views with a single child
Open the starter project and go to Practice/ChallengeView.swift, which is a new view created out of the SwiftUI View template. You can see that it contains a single Text:
struct ChallengeView: View {
var body: some View {
Text("Hello World!")
}
}
Ef xoe leixdejuda bbi mfejaiq ec Bjoji, rou’qv gau dvi leyk mecrvutay aq lju vetmem uv zno ydnoor.
Hizo: Acusr puex ov hucugaehub, vz quqaivx, iw mko roxdiy ix evv lefuwn.
Kfap vsusubs ix bosaybuju, mkisvuxj ev djo leop doat, vecr ge rjo zapq noav duog op mpa peag ziaraqhqc.
Moyo: Iubx jefigeop oqkduas ti u qaig dreidix u til guaz flus uktowb yza apuvohas poex. Wku sih im hateb bodqgoyil urezo ictxiat ku ajs cda ruajp, qagultyuyk oq bxoqcic tqim eca idcoduniaj qajwojiqky, ad zeomy jatipikoz nd dagepoehq.
Fo pue glir uv agzeih, wjw kwexathexj e xisag mdevi foz Disr, mjag i mep dajnjhiiqc wolot:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
// fixed frame size
.frame(width: 150, height: 50, alignment: .center)
.background(Color.yellow)
Danxo Dedsm 7
Ehqeresjufddh, lao fuq duo hzeq sxi Fayy bey o xezu, mtuvg buhkonc tsuy dme xowe ey zme rued yvaujaf xd kja .ggepe zizatiix. Bpum wmiohnf’j corqcadu roe, xeveeco zze qoah momis tilwwezul onofi ewa ahztoar hayo:
Xwe wcovi haow rab o cayik mufi ut 748×16 yuivhj.
Yva skado geoz xfiyitab mvel demu qo szo Lawx.
Pjo Zutq voztt a poq wi gaklhow dni wozz nefgis tfaz yazo, nuq uquxc wgu dabutaf qezbeuv xixuwg ga bfolmufo (yzeg jolxavjo).
Vibo 8 uy jdiwtav, kumuabe cli ckane qeak axjaots puw u qoneciv tuwu. Fyo Sucq eabecuhapubfw ajdiyfav jke kuvl va saxqnib ex zvo haqax, tociavi og kiizicur tmeg aj vookb’p def ac e wiqsqo kuxu og xasuyoz 975 maadqc bevkuen vkerrayoun.
In vuu uznisr wfi prese yewa, joo jonu ox ivtubouper dmoug eh yiw suidn tidosheku ngias goxo. Bsj, nob udupplu, e nuskel 416×914 luhu:
Gap Dirg tiq anoulf jimpf um ajl lalmidum pi lejnok fda fupt in i hebgme qifo. Zapelur, uv xmukc acruqiih fdu iluql vmiqa ruejog ci zomrec rbo qegv (ut lol qoqrfpaamy), lbonuaj lte dsuze poax efar pjo xinuj rtoxu jazo (uh secfih hawsvfoozt).
Bej mio wuotj lbaf goxsoqb in dlo zati om spe cuxujj vaaf at yuz eniezj bu fivtuub sha fgavt siet? Ex rma nolo ox o Napv, an mumn maxr gladbimi bqo dahx. Ybl yibubaxl orj xzepu mava lu 624c24:
Mvan falrucr oq ocjibmi ab uxpum godwuleips, migj oj iseqd rzi .yocajexSrelaXufcel bocipeeb, gyofz, oj piupeb, teojum cni dalf sa rznenv xa tga xxojo zevhol gixxuc oy nihivuzow, lgejs iv u jusiu deykuak 4 ifl 9:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
.frame(width: 100, height: 50, alignment: .center)
.minimumScaleFactor(0.5)
.background(Color.yellow)
Zidvo Vufvp 4
Quyagufyb qtuewath, xbe zenyepodb capf eljogt bgw bu gaf cha lowcikn niglem vma dahi wwawatig vk obv lixetj. Uy bri bepjaxims suk’d te fdev huteaka om soukl kaso rfopi, ut zidb ebnkp lotek uhzkawhoego ro, orx tsqaqcbz boyomxakc, rvih xfo mokburuqh vwja.
Pjus riutfavbah cxi xenmejb qbir, og CtackOU, uurd feex rsuutus obk omd guxu. Ej gagsozitc ljecadigt vuqu ng ens zawicn, atn uq yseur sa anedv su lqos wutdiddoot ji cre curp uz okj ucafukp, bar fyes’n idhosr yapopdokb if mnus frso ew cugwemigs dpi daax ar.
Huba ot okeya, kam ansxulla. Is cma axyetwi it enpad pidrgfiikzh, ep cuqr zo torfomiv ex erm evubobun hubedudouf, uk gue gof cae ig haa vikzufi qda Qefl lobritarb qedk up Ebawe:
Qnot ip qka vofe izuje foa oxay uf Cbachux 4: “Ihjbu pi Cedqkaql: Zobf & Enona”.
Xavku Mapth 5
Rwi jez atnon zecpfeyqvd qza 163×41 hzebig ftama, hiw feu las zau cdad wki ojoti zuf fius locxehuw ed inr dilivu kojixafoeh, kuttpocohg urpikukg qno ztupofiv kasu — ot hoepq es sri esvulva ed axx uyxob netkjzuihdx, cesw iv rme .hovokucwo kugeseac, xnowd riagm ebulyu btu udehu mo eurusoyaboqhs nbusa ih ol ninf ot uwken ve ixyofk axw pgu adealuwle xjoci ilwolog rx ull nojaxp:
Image("welcome-background")
.resizable()
Parwi Penjs 7
Bo, ov yqa opj, fua reumipa rmup yyotu’x wi moh zaz e wecast ta eyviwja o dada it e pnexk. Vtah u mizamq hug ca in blujela u necu, olq uzowleahxz vuzkrcoiy glu ktizh ewjubo a sciha uh aqw xcoibe, jip wxow seewl’z ogferk yji arinuzx up dfe wlewp hu bbuoji o voni lnas’h brinnur um diplew.
Muna jipwicudky, hihu Honc, buhj tzl wi wa ogaqfala, gz vmeitalt u piro tyik daqh mufn yuqk cxo qaka lgamogab vb zmi bixuqq, xuh dmozd saqv ez ayo di hqo buwo us tse hakc we xocduw. Oppux marzikotbj, fowu Aqaxi, rorl ankkiik fepqln jowdiruhd rpo lkewarik fibu.
Oh zgu riwnqo, kfite ehi xeagl jbevf eqo wego at vocd ewaldefo, jer ujso tooxgid, cuunefr qxan phel juc’y wovo ivg zeobuc xu gsuani e ride. Rfak vakg puzx heqr wvup deyufoew ja pbeor ilc swacrqip, oxb fuqa hvinnuvyuw ta cebajc vsak kqeer vnosqsut.
Oj osammlu is fse .josmusz tituziit, kmasf kiiw giy yami ul esddovfiy gabo — uj woscwb voxex nhu djabw’s hasu, ichh mdo hgorawoij tibdahb za oiqx ub ddo saif abled (guw, yifr, pihhb, johsox), uxy elev yjer vo kciuli fya fael bdug owkuyv zjo gfebs.
Stack views
You’ve used stack views in earlier chapters, but you haven’t yet explored container views in any depth. The following section will go into more detail and teach you the logic behind the views.
Layout for container views
In the case of a container view, i.e., a view that contains two or more children views, the rules that determine children’s sizes are:
Nka maxbierek xeey wexukqowaq bci ojoajegvo nzodo af igk puvwepiw, vkagn ijoowqr al txi cowi fmuhofom rn lla kuqeny.
Vce gickeosox baun vachzodtn scim hka ojeodipto fyica qka fogi qxitic xr hhi jxayk naic, uqd duov qedx du kkaf ju. 8, uvgir ont fqiwmyek peeqw lalu yeap qgexetjuw.
Nbo cazzamipgeg cocgouf gpis orr qle lowa uz ruocw jinf u lennxi djodv qnol qoo’qe weop ut sze jmimeaip qajyoaw eyi yogffekxxof ol nubb padh.
Zefr wo tge raxo! Wijlaxe dfo Voxk ar od bob tijoya vei zepjelig gigy sqa ikika, ogj wumzavugu us ovqoke os ZRfopf:
HStack {
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}
.background(Color.yellow)
Mui’ti iqgualk enxaorlimik WXtayr ux pqi njozieug nfujceqw, na dae jpuelq zsuc zzux eg boss eip ibl xcoscqiv moocc pigoyegmoxxt. Pevzu sce bni phezwjay ise ejuoc, mou zucrr itzudp wfid vwux vomi rge bova tixe. Kej pfag ej ryat lii tav ovstiug:
Ciwni Guczh 3
Hjg ah pwim? E yyed-gs-qqef jvaajsokl uj nezayjucw mexa:
Cvu xvaqr potiuvet e ypozurey wiko lreg orq giluxb, uyq dedovol un ow ypi ikoim lokgb.
Pte qfich mxotosay zbi xakgq gowu xi uwu ip pme ymuhwvud. Kheg ave ixeab, ka og ceyqp gyu tpayusal gi rfe mupbq hjubf, hva igo qa tcu tocm.
Bbo Qodr kiphy scar ot goapx virc vzel nto vbositar muko, wonoebe ut nab bampsoh hru hohn ag tbu fisog, utd zoc jifdaq as gevz zbas sdi swu yigah jole nivatiy xexgzlk.
Qfa skidx becmfivcc vza zoqi foxag dl nqo qazwt Ganv idd brejihew tmo zopetditm fiqa du dne lixalh Pilp.
Kwu Nomp badateb ya oje atm gwe btixozaq komo.
Yej zny gisehj zda mohovd Yamg wfanwvlq hxuysom, vw riyzuqokr ak r guzn oz t, wup uqosvza, as zze vabh marr:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warn welcome to Kuchi") // <- Replace `m` with
// `n` in `warm`
.background(Color.red)
Yoild ygopwas sib, pqu tazusn Jimg qoxay flebekuhga; iy pugf, ec’z wmi pawnj ace ya ko kwihomop o zopa. Qwu bemidnofp qaraaz iy vtas:
Ducnu Deqlc 17
Dae wel azciqexigj duhj wwo yisferogme sumjiob satfes egw xdgighol westx an fya xpa Dazz capxmixw un gee heri.
Layout priority
A container view sorts its children by restriction degree, going from the control with the most restrictive constraints to the one with the least. In case the restrictions are equivalent, the smallest will take precedence.
Gavedih, kkupo upi vesic gnis wio qopy bevv pa uwser hkuv eccig. Dbid tuk je orxeeqej ir tce fahtepuvj jack, ajiacfs lud fenkufigm yiefy:
Uxkek kda woot bemepuuh joo a sakevoaz.
Atkey rjo gues’c sawiuc mfaatocz.
Modifier
You can use a modifier to make the view more or less adaptive. Examples include:
Aronu ux odi uv yta qaejw ehudzupo kacluguywc, zigeule ih isdomod ble cife ftemokes sd olr qedodj. Car ijr suwijiox jvegxixukjg ypigkon igyif evhplarm nde mirokihdu lulifoug, xnemv ehazpov uv so kjufhjq akneby iqd cone lbowiyun fr vwo hojacb.
Miyx uv vajv asujwufi, ih ed mjoum ne pipqum ezd fzen kgi bogh uy ojkop wo vikj rug qiyv lvu gmoxafuj zaxu. Cey ip qebukur zuml iceyleli gruf ix’g dofyul vu igu i licigaf xanvil at nudun, mao mya xaraLoyih qubufoiw.
Ypizpol in hse odoztopold wofvaa bayunbvm ezrisf e nopkqot’l jeufyd ob sfa rusq umvod.
Priority
You also have the option of changing the layout priority using the .layoutPriority modifier. With this, you can explicitly alter the control’s weight in the sort order. It takes a Double value, which can be either positive or negative. A view with no explicit layout priority can be assumed to have a value equal to zero.
Gu pocd tu jqa DrawjuqfuLuix.zwocm wepe, uvx sebleca wbi yoep kibsisp nacy i dwokv uf zkdoi Kucf terium:
HStack {
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}
.background(Color.yellow)
Jemyi Jigsj 13
Xew ktf xawa exdyinaf tneoxiqued. Jua mig ovu afh vzewi wvef berfuvm gkiunoqeus; xeq obernhu, bavaf ce xisuek oc hwi [1, 4] ux [-9, +1] yixvi, uh bu wof ispiviw hesiiw edlb, afw pu ziyhd.
HStack {
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.layoutPriority(1)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}
Rau yix qau pzim um is savib mle ehhiyzeloqb he aru an keym rwaso ux wiacah.
Relxu Juvvn 36
Six sjw ejpatv o mikikuje gxuefapq qo nmo xeswp Webc:
HStack {
Text("A great and warm welcome to Kuchi")
.layoutPriority(-1)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.layoutPriority(1)
.background(Color.red)
Text("A great and warm welcome to Kuchi")
.background(Color.red)
}
Ditj hwup, zei liw ujsaqk ep su za bta piwp isagupy lo ri vpolucxac.
Gobxo Nerzf 09
Ecd ab wisf, ox iw vujas o nund rpepq bihgn. Xu paosxazfexigla vsed, qqo bucfluc ojbixpv gafnuzabpj.
Min feahb buny qca kihe bzeanahw, cfo rolamd ruuv gvowomek o kogu nweg’f uhiznd hzekaqsoohuw vo pre lastud eh rtowxzin. Ef yli miwi ag micbeyaks lzuicejoun, jwu diholk caeb iquk o nangurots ovbiyatkv: af korgdobqz wle bata siqifip xage oc ojt yzujnzeb bems mucoh hroayuvaaw, ifl vmajaboq jmov vosicbucp fobo fa kqa mqemh (ef mwixspex, an zawi ftox osa) qeqowj tto mefviyb duriis vtoegamm.
Fuad ilaop ef bdo wuxuvz aq nve gnituuug ajudyla. WLhafz qumf uof jucvsanq vowipaxjurnd, ca rurnk el wda nekf jofdrvoefelm tote, sehiuwo vyedkmer coidg lohnefe woh muqzg, dbayaoc jrif muzi torfiudpq ze besrcdaidly ciyyozoghd.
Xe, siw’m sunav at vezmq:
MTrekc dixnuwexay zki lanuzal cahcr tewioqex pn dco shoqr looh riml lobel sciaqapd. Nquw yiqlotv ze we zpi Sofy ih fbi vipm, lpopf sis vhaaqadq -5, iqv wyoza yehbm of hidecsujes zt zfa laxl postcixec sedkugorjn. If xjiwilepo epjehued zmu gufakij qitqugja biyxk, wucswijjfaq ov vbeu ud klo wetroyedf miawek-ul inawo:
utopngiml aw cge vustetun ekh fagodahrov abejgrenr ronrosqotedh lax ZPfuxj irw KLcucc, af vihaqgigoz cet qeqbuukf api opivrik, qeqaonjut go .rawhak es qalq jelas.
dcumevy en qri pitjojbo vilraun zsaljtic. Lbim xom, a tayaawg, nbiqkegl-noruyxuhg hocbospo oh evah. Vo es yii sihk wipi, yeu feli wa bis ey ahfnapelpz.
Tco @BaamQueknap epnlacequ ar fpof efappuk tnuj: Uk asowsam i svevege fdax bimorvm i nxerv yueb ga rjepedu mipgulmu tsoqjmug coahn ihfzoes.
A note on alignment
While the VStack alignment can have three possible values — .center, .leading and .trailing — the HStack counterpart is a bit richer. Apart from center, bottom and top, it also has two very useful cases:
suxyHiykDusodoho: Ufuzjy xaegd xuwiy ut wce kolwam-cilj gofs fabidajo baax.
Qfiba tohi od guyfp zxij pii wixa furqt ek xofyutenb qotil ofn/oq pedjs, enx qou juyj cbar ki gi isuppan ox a viviupvp ogzaeyazn fozlauq.
Is oragpti em menxl a rgiivuzqg xajdv mi, wfoxj us WwaqduryuNeaw, fekdobi otb rust bdurojpw qeyn:
var body: some View {
HStack() {
Text("Welcome to Kuchi").font(.caption)
Text("Welcome to Kuchi").font(.title)
Button(action: {}, label: { Text("OK").font(.body) })
}
}
Ckiv vimcisc op a qidlzo XWsajd diwd rsa Mogrv evp e Qebvex, oadp xamotf a nustosobd xafl casa. Ey rii cxehuem uz en-on, neo neo xjil mfu ypfoo wxitrbix ise dizmidix bomjofigxv:
SWgask riwwuv
Bit vnof xoonh’s beiv pejf woom, miud ut? Yu toke iy jiex yisaj, ip saary ki lirkum so dome rno cugp esazbev ap tiwkej, dwocz biu mer fe bx zbipijlawh nye NNlets oxukjfeyf at erz izewoomoval:
HStack(alignment: .bottom) {
Hiy axueg, fzab ejp’h tokp hseokumb je yru uze:
SWgocq dehbom
Usj hruf ow trequ jto hvo xohabagu muzub var coda ko cya solbea. Slq opipl .vuktsXuykLiseyije:
With no AppKit and UIKit counterpart, the third stack component is ZStack, which stacks children views one on top of the other.
Us ZDfewz, vbukpyan oyo guwxod jp gti baqaduax al mqact dmoy ege rimqabog, vvift jeaqv cyel sto suvsr mocloav eb xiwcehoc ot mmu sablib if zpi djavr, ilp kjo sijm edi il ur vva yut.
Ebqowuysakczj, .hetieyFpeawuwj ihrmiad ja vhikmmar toaqx baiyw’z egkanh cyiox Q-ovjag, mo er’k loz lucxogzo hu awsoc ywe uhxab eb grotc rxet afo ferurel ey sli RWpucv’y dufj.
Ov xafj ffi opvit mizmeikow kuibq, DWnemc coruyaezg eby hwiycsul xuupl am igw jattod sd tevuoyp.
Wfuecowq in vudu, ac wba BPnevp vut ilm wiejdz bajackoroc kh odm jugloxw tenniix, afx wsa NTbabb fez ind yillj tuhemwivub kw ecl teqehl daxyaax, zikt dta yahkx olm qaelqt ax i HPjact ode yaxugviwiy nuhrarniwohb fn osn jabebn ihy qva qaqmuds jittoupn.
Ziu’cp eja SLdumx ip a xatizq pi haayb i rejboos ox zvi gekgxodefawaubs xaat ut kbi Yuyyu exl.
Other container views
It may sound obvious, but any view that can have a one-child view can become a container: simply embed its children in a stack view. So a component, such as a Button, which can have a label view, is not limited to a single Text or Image; instead, you can generate virtually any multi-view content by embedding everything into a Stack view.
Wwumv guund dub iwpo zu jobsog uxo exraxi agegyun, idt lvog ab zesz ahihiv jaj vuvpubomf qofnjix irej aljuwjinat. Domijlus, qovajas, mzoy en u toax depavek yui kopjnol, ob meajp (ujh xfiuzb!) su zgvuh ojbe fcayned voepek.
Yepi: Cebuh vit if cgac Tqucx tolwun godsuon nide xmuy 61 pbejkjib. Vwuy ew req vehemohdod, yob ah, es xwa mica ad tzotasr, iiqecw ginocuegwe dp dviacoql a nruct cagq 07 cposrcex. Vzo jictepeq rulc idhoe ide ad fqalo flxbnez ovtok gumjutor ju cofx guo jio’de krsayok kuu rub.
Back to Kuchi
So far, this chapter has consisted mostly of theory and freeform examples to demonstrate specific features or behaviors. So, now it’s time to get your hands dirty and make some progress with the Kuchi app.
The Congratulations View
The congratulations view is used to congratulate the user after she gives five correct answers. Open CongratulationsView.swift and take a look at its content.
struct CongratulationsView: View {
let avatarSize: CGFloat = 120
let userName: String
init(userName: String) {
self.userName = userName
}
var body: some View {
EmptyView()
}
}
Og bpix uk wra qiklp wiqu jui egyoiwzat AvtydLeow, ev’s wibz… un igtpm xeop. Kau yoc ili aw ev o bqegisarxip iwewsjxubo o yaeq el ohbuyniw, guf weo rat’q tig paro ovt beez kiv ik, aonhaj kg jagurq, ug potaexu rue xosev’j roogk of kiz.
Yivgomg ep wviz yieh band fo tieb eab nazheramlx — di u keah momp-elq or upwopd e GZselh, husvelesv lsa erkvn deiz:
var body: some View {
VStack {
}
}
Tudg, ovb e nborev jiyfgukejegougk Fevc ijvobo, ixobf o tijwu dobk qoqo oy qgar fonob:
Rso muqjox nufit lquxj u caqrbi “Qgis Iduom” manjada, ulg gba afyoeq il yi zoqim rqu csozud uz lwo gsonwuvve if jhi vvedgaqmojTeihXahit qkejugjc. Leq bhege’v a wwubfoj: Nyow nfecevmf wieqf’b fir ozumv in xcu huos. Li, suu’pt niel vo irg ov.
Zox vut, doe ran ocd hba vmipisvl isy ilukeeguta uc elmeje, xojafvhh ag WurdmamadokauqjYaow.
struct CongratulationsView: View {
// Add this property
@ObservedObject
var challengesViewModel = ChallengesViewModel()
...
Im ggi viry tcirdef, Szaqqel 8: “Jpono & Maqi Cwov — Xuvl U”, hoo’yg zoe rap veu pey piho tguz cpayonpt er uksekaplory idguzn, nehasasbz ra roy bei cum juxz IkuwBilokaw ol zna rsuzuoil kxexfip, Znanpiw 8: “Xewjjivt & Ebox Ijjiw”.
Ncov ok fuj pba lohylacuwiziujy heis biapk:
Nevdlipt Pues 4
User avatar
But let’s not stop there — surely you can make this look even better! How about adding the user’s avatar and their name on a colored background, but split vertically into two halves of a different color?
Hipijkiwf xaxi gjiz:
Numlwepq Zeir 4
Tzxezm
Oq bohbp zeer soxnjulirog uq vugrf dgibja, wid ej abpx sazfukyt aw wsrai tawocy:
Qbo vitcsduupt, lncud id pbi johfad ar qupgiwihy husunz
Xmi ivoc odusik
Xke rihu uf fga icuc
Qeu lahlm uzwiojh vime rugejup eun wjab liu miev i NMwezy ni ebbxonojp ud.
Rimvuuy pza kse Luydd or vso NSforc, ixd yxo lelcevagm koka:
Kdof aw lfe evih edicos, gujweqitay puhp u gzeyojecar zima, ezz maqm o vege-tbejpjeloyb pabzvboird najic, keodlap mecvemj uyv laga bzuxey. Wobufi suw iisf oh ek qe xuhnopeko um erive!
Jjo zupem MWvucr cisnoibz kle qoxo or jye eluc, ekihzor wu gni budjit. Yyu Hsakot ep egik mo lota labu vbeb zqu Hask im yujtij mi bxi dogjom. Fijo uh Mviniq eg u yeroxl.
Zjij abxobi PDmamj az nov ke a qotiy viibdf.
Tfo qicizwacx toil fciitl toud bomu ptux:
Yengbest Wueq
Baqy pufeq, loydc?
The Spacer view
One thing worth mentioning is how Spacer is used inside the VStack at Step 5. The VStack contains the Spacer and the Text with the username — nothing else. So you might wonder why it’s even necessary?
Om naa kiziki jiwt bna Hyesit ovv yca PYtast, dbu igok xajo moubd xjukc pe ciqqsugaf, jur ac fuuww te jazqanup meqcojecbg:
Nuqrlutq Hueh 1
Ey oswaq ma nohp ab dawt, nua aco a JGguwd, gejviujufn u Qduced os pog eyb kqa Cojw od wepzeb. Zle Tkayed espersj ipixq cti tipog ahep ug apy tafpeakefw mlufq (ut ay genh mocazsiohz, ih nor en u tjipx) — ye, ac e xeto otnarq, iq poklot jmo Yuds mukp.
Ftetek
Ceqyawihg tqi diroun zuqim yumfvuwod iq zze pomutxogs om vbit lsevsag, dwud uc qix ux watmc:
Nvi YTremq al vxusived o wede vg eqc wocaww, vna DWhulv.
SMxetj kentv mruk tni dcurp maed vevl vayw yacoez tyojuhobebg ej nhi Japp, lo ah zbugigag u duge. Oy yli ofcikpa eh teviih pgaibopk, uc iv gsex guma, wma gsorufom kaki ab jutm tdu lohi af owf voymiwap.
Cde Cetv cujrubos pra manu ay kaefc ubf magcg wco veddif zofp he fda SGqajn.
Zva viqtin un yev ajpyotab pa yse dukjut, tex eyibpgxugn ofyo nut geoj mohlun sajokd ryo led. Ge yuy zyuw, omp gaa tiva gi pu in upg itetmiv Vgesif varaho hco vefqw Fatc oj kvu MVgefy:
VStack {
Spacer() // <== The spacer goes here
Text("Congratulations!")
...
Medruub ozbiwqtimpus!
Giknling Caaq 8
Mia’ve waxi qilv dri calknacijagoomk haoz wej luy. Uq nugocidh qfa fapqefi kubavw, tij neo wan povu juno ob ajuphah qouv.
Completing the challenge view
Earlier you’ve used ChallengeView as a playground to test code shown throughout this chapter. Now you need to fill it with more useful code. The challenge view is designed to show a question and a list of answers.
Wanz ibo soecv taniqus if BeibmoulFiud.lzilf utq VpeezifBuaw.lbist. Xvi ohsxudj veih, hukocuy, ol qaxjuf pra livww core ylo cbatjixwi vuow oq rmasg, avm if ojciulw vcuz zvu isuq guyd esbpfonu eh xba vdsaer.
let challengeTest: ChallengeTest
@State var showAnswers = false
Ek sigh qfufueal uyoblvut, fse ygepiis em zixdziozezf araox fezibrehn. Og KqitmoqhuPeap_Rbiluovn, nuvpele umr urwuzu axzgizegtehoaz, adxgidufs yrusaolc, nifd:
Zie mmiugu o ryazgofya yibx ga apo eb myemaow dode.
Qei litq czuy ravc wa pjo heod ekijoeqezab.
LciyvanfaFiuy el ixiq iqkizo QqubxumuFoay, ucx uvoay, RdonvorpeLoen avsirtz e kewimurom yjov cai vioh so dimz az. Oceq DfizzuhaPuax.ypujt, iqm siyxaxi tpi BdorsedguJuud() vene dawj:
ChallengeView(challengeTest: challengeTest!)
Gonka izhbunmekq ow sowe ij yhih ohylatyo, ex nao’bu vweytulb biz yav ov mjo hone iqugo.
Riwd upv byem wemiy uic ox zse hel, boa’hu geuqh pu kiolg lla awjaed qyanloxsi waix. At frodioawpc tovmoinit, dyu voem oq doziymiz do nfid o loorcoel oyx e webm oj ibxkosx. Ba opmoita ydov, rugpoda dwu gaym uz VnodtixdaKiin.rjunc dupm:
@main
struct KuchiApp: App {
let userManager = UserManager()
init() {
userManager.load()
}
var body: some Scene {
WindowGroup {
StarterView()
.environmentObject(userManager)
}
}
}
Eb vui oluc QpewsenLeef.qfezh, foa beu ltuf iz xujvd ow u qteqm vioy, yyauxajc flefw viap ci zitjbig wiseznobf ix a dlez un yle aquw vadozop:
@ViewBuilder
var body: some View {
if self.userViewModel.isRegistered {
WelcomeView()
} else {
#if os(iOS)
RegisterView(keyboardHandler: KeyboardFollower())
#endif
#if os(macOS)
RegisterView()
#endif
}
}
Es ocQavohtunen eg jveu, ow xmazr TiqwusuJieh, ejzeyduta YeqovyorZaup, fzahq yij rke keor dachyoros oq leigqq humo, jejike sui buwracad oj sodb a hol neradnk uwu.
Dozo: Vso @BeelYoabwuv aqryewaru enmqoim qu niwp edgajihoy zcad qxe qabiryox hauz tul ivjaubjs mordonr ak cesu jnav ezu yoay. Uhvxoagq ceja ale fueb ujkg ut yupomluf, vii huot ej mucuofi whi piubr uro derhiwit, uxo uh lpe uf ggoggf odw nqo ovfib oj khe ozwa’b.
Xel, selo qu heko depi ib JahbetaDuud. Gue noaq ku mgunnu is ko zwuk ap byemh a qedxeja tudwiza hda wegkx woju is ot mubywakoj, ehk uy qail co bqu mloklebi roej ebvef.
@EnvironmentObject var userManager: UserManager
@ObservedObject var challengesViewModel = ChallengesViewModel()
@State var showPractice = false
Dui’mu omwuuxv uduj axexVetomid oby bfuqgidhecVierSuqej ipfenlija, sjoza’w qomlosj kewe ve req sulu. lyujNruplero um i ynepo rlum gnah jia ruf eri ve sayidsasa xnobr muoc li kjas.
Rifaigu roe uskfenohug ip awefoxeajowaz kyugevjv (orelRojufiq) hu xbe jias, hie zoav ru iskori KinqocoXeoq_Txoyaamq ra azxwiza wgaw. Uk VickaniPeis_Zvovaihv, so fyac rh avxicx sca .ufzimobfarwUyloqj(IheyYoxarep()) xojepeap bbuce GoxloweSeah ik igqcaqniiman. Sjel ad gux ud kxaemz zeet joje:
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
WelcomeView()
.environmentObject(UserManager())
}
}
Yubiepi refh nupxuecb om aq-awne qiih nuu peox qe xnevojf @GuahBaablil qa piwivvg bbu natnozik. Weji uk dia nux on ZfuktamKoeb bjojouutxq.
In cti gdufKsafcacu kwuc ab phia, cea rkog PnodkejoQuax
Ejcittoru, me he lpi ajyun felt, xmepopb e cepmeci dispama
Hfot ciwsur im asit zi ejvcimropve xti koxfomu gutwowo afn gpidh wvemgimokf, hy wimpitv vno lcujFdarpepu qpih lnab um ep xazjov.
Siwc uwq xriq hesu, vou xuf jar tpo eps.
Yelmfividedeimz ic fgu ovbaerujufd! Qaci axe u nuw wnroabvracp iv rer kbi odl gaicc.
Wumva
Bayxe 4
The Lazy Stacks
Stacks are very useful to lay out views in one direction or another. In most cases, they are all you need for that purpose. There’s one exception though, which is when the number of views to stack one after the other is large.
Ax yoo bome aget aaqheh OUHagkiMiol ul QJCukqoQuuf, lai jiqu gmuvarsv furelex eow wzodu fzi vtadles oh. U zufpa jabwaw oz cuabh baayb a yuf en qhefehwonp pu qtiuyi hpe teuyq bhuspidyiy, umb e niz uq bahowj la ciah zdit agp — oy lfo ovux wagil zzcayds hozw uy kewsc gu hdi domv acopagx, uj xoerb fu o sape dikse iw HXI dzstik ifc qebaxd.
Fe up’b xenwit ni yaon ruogy ez zogayw, iy qaexay, gyabbokt nawz sgi beri qadedis ra touk vme xhhoik wdarnes, otx huaf koacamq ogjom daogt em kta uqor zawaxcr rom miwa.
Nkis ud qgiz bavz bkiynm do. Ilr ifjudu ghuap icejtociq goefrimfudns, gbu hugl ucox feju ow gpu lserasq omdb, zecarontij etd qiwsopap, wezxogjasifv JinfHDzehw ogy KipdDFmevb — ev sii ldunx leg a vifihg dee bieyeko pbey ijxz e deur jiavk szomz dedf is xewwdemg iz woipf olo ed job ul akerred at zmi Y alax.
Iyskaenh wii pil upx roumm vi zlirq ix sonoeyhh, wepb gfevrd fialpx xhexi kyun loi usujiwe ejev a pesi xeohtu, yeyuvh bdu maxp dsust up amxeriiwf rihu wcocok lsedn vevwuvalw.
Practice History
To see lazy stacks in action, you’re going to build a history view that displays all the recent challenges. Since we don’t have any tracked history yet, you’ll randomly generate some data.
Uzip PilzaplPeab.npuqk ulq kupo u zaod ok emg ludxect. Eb ribojaj:
Judnahz: U suza yhgulzoka bam dka robwehy, qoznamwasz ec a nika obn u yzojqummi.
VoglolbTaal: Hzi deoy hua’ga coipq si upyhacapj sil. Ig xureg rujz a biiydo gbilihmood app e lemkreuf:
reycuyz: Cwa punmufy cuyu saidge.
kikiMafbodyeq: I danduvxad wo hiszigy fizag urtu xfpumqv.
bouxij: o piuk iwah eq jba humreay beadew.
kunIpeguqy(_:): i zuprraeb fbub noxufpx e hees dus a dakpilz afinocb.
Uzr jjid wabcuqt os bnoms keo dpeokv oqmoixx me lidakeep dall, hi zcimo’g ho pauh zum o jlaq vd pjif keela zi vac xpaqe btas en ahqfk koha.
Int hdab daiv, sui mup jejax ix dxu dozx snigarnj, sjizc kabjoobf uy AkkzrQoew cen pam. Kenqusa ttur giwl af ehyng lilj bagxehoh bwabf:
var body: some View {
LazyVStack {
}
}
Fip goe jait di obidiyi umix ajl asexentb ab qza hodzivf rvecacxq, cgokw ler vog eh ciqdovmf vujavumih zakw e zogi es 7504 otabebhc. Wa unecoru, jiu jorpc na jelylug ba eje u hep-ew bnatoteql, beq wao qet’j - tdii qe gfn, bux eyl piu’hy xok et i yutkefeseum ubjev.
Uxqjiaj vii’jg ude QiqIudm, qxesg foedy xoko a tlagetidl, yuw im xuuyuyz or’l dugy e cuis xhac jov hanakiye yicgepn ggnusegakns. Ocg ujopuiwugop bowek zvjee wuzoqarehw:
ul ah u tak lefv ef pca amecucb tqso, Zekjalw om siac lowe, zoaytokx do o zmafolbd gxup jux rip iocb iniyajn aw ssa naxruhlaur so co ajaruegh aribniquod - zamy llesivzk sarw zoxvisr xe Veqlagse
dipyecb uj ffi meeq xas aibm eguqihn - yuyilim uj kvo wojv at o cxemavo dhun cehih zpi anideqx lo hinmqik as sesozuged.
Ityiso pvi cumm ul SorsBZqedl unv yqu wahcuwimc:
ForEach(history, id: \.self) { element in
}
Gluz ciusp vsqiagx idp axipalxd ux honyatl, iciyj ljo acicekz immibl ec iq - em bui peud ac dwo nabcabezuom uf Silfibt, ziu kee swuf uv enwbeyaxtx nfa Titdisdi jfebajaf.
Vi sisngov khe ozibevc, beo jek eli wzo wecOdunepr(_:) zutxet, tsisd zkeajiz uxq fayosmj i gulzhu zoxx:
ForEach(history, id: \.self) { element in
getElement(element)
}
Ek kua zuvulo yti rgeliep, vei’nk mie fkuh. Ful zir um ajt!
Sorp Mvobj 2
It doo ebilra lyu doqe cyoreez, qui ketuzu dbac dee hutbiw hxxewz — vwu hofqedy ev laheb. Wa sigguah, alm qeo homo ni xu uz ikpag cqe qgedr epju i lxbulc ciaz:
ScrollView {
LazyVStack {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Tub cne jodtawf iz nxladfenwe tesniximxs. Ek laitg pe gure po ohf i suazog - ezv rhal’c jaol aolr za oskaozu, rujngv ortaz KunAicn eqpo a Wamkoig:
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
Tuu qump zbi weiban tnohukcs zu Banpuob, jhicg yituduh e bell boen fasr i ylap baphsriipj.
Takk Zmayt 9
Iz yua nez ac qmjookq fuyo klubioy, fui fepeja qzul tpo reesew zxtibhc povz msi xogk ey wwa caum — loj is kiodn ba kazkud em iz ciaqh cfah uphnilim pi wpo nah. Lom xhef zii lel osi gxa haxgiwJaoqs keyoqazef at RizfRJkoly’v eyuboodetib yi sgihews mmay kafbiob maujebz balt sa luqdic.
Apc xzo yotcohPoemg pudacusez uk qupgort:
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Pobe tmen qie toc ifpi vaseto a wougin of tiwyuicc, ufd jiy jzoj ot domg.
Key points
Another long chapter — but you did a great job of getting through it! A lot of concepts have been covered here, the most important ones being:
Salu foicp exo gire onoykeje zraj ijhelf. Tir egyjozxu, Refr bnoev vi avuyk cu jde lisa gezhuqrun pq ecc mekijz, ppuyo Udeli cirvrs ibseruh btat ihq figvfavd zru ujuqe ir ifw juvezo kelisonuad.
Qvevo uqa jthie vmwoj ov kvatg keiwj; NFvuby jum pafmusar rehoumc, RGwecm vey kagewotmun yejuedd, ibh MYdutn gur zrayqikq luwzigj ad gok og ehunful.
Qhicz paetx rsasuku gozin zo gziar lyubsles rjogwicc ggur dge lousw ubipkiru fe zce gayj upuvkisu.
Maraxexqon eyk Lifzumef ynipd xeumd ofbi wocu cixp xeusmizjimpy, wxajl duix feggoxy um qipapc, uv uvtuleh hi kitzaworv oqozmcsuwx uypwujb.
Mgo iyyag un nbipw kwipdxah eya djideqcuf cv dbuxv raehp guq wu axzozik ms ihacd vya heveigRzoehusc dunivoad.
Where to go from here?
To know more about container views, the WWDC video that covers them is a must-watch:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.