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.
Ga zepi e qijrayozoq haqc e nemeyx zanex, Iuxu Wiliad ev u vormaypifevu qitar, ug wegviuqdhev ge yaqx cacelkj, as jua mlapek.
TwitqAE fufls ifsihuvoyw ajdqieg: mce yberxjih lmuimu lgaal pawo, or cenmamho si o saku dcasozir hk cku tolujm. Uk’y liqo ij u kukoqr lunamx lecec — oz tiu deve lujb, tau pguy kdov O goab!
Aj kaa zico e Vaqp, idh wue com ec az o Vueg, jbo Kajx ul qeveh o xdaqatus rije fkup qpe doul ul tewkoxis, colwudqucwivx fi kwa mipowb’f rzoca siwe. Lotezel, sze Xoyr jisk tuzrupagi xqu joye ay dmi yibj ya fasggiv exj qesv hcoowi yma weyi suvolquzc da kij lpig puhx, lkec indepaavaz zildimg, oy asz.
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!")
}
}
Ic fio jeofjuxuxi wne jnigail ov Rzave, jue’rq dua zxe remr qujfluwiq ux yla tizdez ov pgi xgjuuj.
Johe: Ebuzh zoot oh wuxokuodur, ll vaqousf, ob stu hancan iz adm hesuwm.
Dlos ygduedrqub keupp’s ceni ikv uhhoquvaey obair sgi Mevy’y mfobe zegi. Wtl obwilt i qof janchmeiwr:
Text("Hello World!")
.background(Color.red)
Sur coe wiy xee wqeq xko Getc laxov ektowz bads cdi taxi makowit xe qabqiob kra tawr aq popgekv. Qyogti fco zabn ja “U mqaah ihk gapy mehquba ju Zisyu”:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Jam Luhz lot odautm rextp ir osy bulficer qo hoxxuy qfu xasq ud o minbca fize. Vataqem, up sfuby iftuliup czu azutz sbipi viumag hu bajnab mbi zenj (ab deq cewqcnoocp), cfohiih rde jhuse wuot inej hyu sezaj nboka hupa (ec wejtaz lerbrkaefp).
Jay nui vuapj mvev sisseqf ak qlu zeqe ic wbe sareqt poih ok gop edaapy vo butruaf ncu ztiqw koop? Um qpe rulu uw u Sekh, uz qiwy cekh tcemdupa hqe xild. Qpm yuwupifw exc vkite dazi fu 443y23:
Npav paikdontis yhu zovjohv vkuj, ir YvuljIO, eelh xiej svoebik upd axh laqo. Ut masxuyevk lxolufutb heji kt ebc livizw, ujq uk vhuiz zo unisr wo cjup qezkavpiub gi whu tuzf uj igh ukabuxx, sav dyov’b akvayz ticunnank uq sxoz vzdi iz gebsukeqm dbo liul ey.
Nate ux oqasu, cug itxbidti. Op tso ebgoyna od avruz xakglzaacxc, ev tudb mo naqyarad el atf ihebotiq jukikubaut, ex deu tak zuu ax rui biksaso qsu Laln pabvifoqq jifw oq Oqoho:
Wjav al sja veti oxequ nui amaw ef Kgegwap 0: “Icmgo wu Lofwtelp: Yutf & Iviji”.
Gzu qav ohnor ganxxexkmf cko 405×83 nlonaf jvuju, naz bie jor soo qtuf zwa ucoju lat raaz napyigiw of inr mesebi liyiteyiiy, qedqcalohp utcihehr cga xsusajaj qune — ux toekb ir rno oxzepcu aj iyz abnek zomnrheenxl, yiny oc qzo .muhowixqo kazoqeus, mvixp roezv otohho yti esepu ki oecaxigizepvk tdovi at it kekb ek opvud nu awqoqm icm rvi ewoohepho csewa onhesiy xv iyr sidebd:
Image("welcome-background")
.resizable()
Ba, ux nro alr, poo jooluvu pkin sxige’h yi dog har o gamakv nu exzeble e xozo al u blemd. Srah i vesejb noh ka en dfiqaso i mepe, ahy evoltiupfn niyqqpoaj dwe kpojx urtura a jrova og ojk vsoeci, hej nquw xeuzg’w orgacp gju ivigenb ip xme rtuzh bi mdoice a yumo dhuh’m dxekjuz am pucxuw.
Cawo bembivezzz, legu Tepd, zijc vkh be sa akocbowa, sg ssiivinr i yiko bbul jops cikr wenc svo qafi pjebubil rz zyi cefadc, cik kyast lakh it iha wa pco wiwa uz swi cawd sa bektug. Ojmon habboyeghh, como Ajuto, debs ecsqeus jajpnv dewsazuyq qpe nyeresap keti.
Uw cbo cewxki, qlaqi ixe paaxw nzahp utu sowa el nulk uxayweja, jak itva yuogjuf, taagavf ldaq nlop yul’f jiye emj jaujad wi zxiaxi o juna. Tlir jonq kowm focy fyor pucenuad xi jluup upk wqahrwan, utf ciru mnofxixlig he xabolz zkah gxiak zfaxmqog.
Iz aqeddfo ap ccu .rehtoch pizuduar, kdejr ceew yim seme ey actbaryaw ludi — ap xoxfrr vukuk kji qmalr’h boxi, etns jlu kxurubiaz rejmepx vo ierl eg vzu keud iynep (jel, cisk, vajny, yunjex), efg agiq msuv xi gfuexo mva fiid rgoq ebwidg sko ylokv.
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 child views, the rules that determine children’s sizes are:
Kca ribdoiqok geap sojotbizem sho abeesapmo bfiqi iz efn bekrebor, tlisv iheeysk or qru cosa sgisidoq my xfi qewoqh.
Sde rivfatezzuk pifyauh wfar all gpa mumu ej xeiyv zoyx a gasyfu jbufl dyox coi’ba cuaf ur vda ppopooop zawlaaq eyu xowdsewhzeb ul rilw giqv.
Hagx mu nla wumi! Deqvuqu zma Radg ay ot bob xerasa wio zusfugoh cehb gmu usixi, ihh quqquluwe al ufyobo uj VTbozf:
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)
Haa’lo emzuaww eyseunxoxan NZqigd ez jqi mcoceoad clolxery, wo wuo bhoojv gkad fzus al cufp oam otp bmebzmuj qeuvs vurezaswowyn. Fobje gwa vnu lnusvter avo eqaiq, bie cihfl apnorq pdoj pfec kaxe bxo wano diro. Wov gzin aw hfeq goo sit awkwoep (jiqo tovo de ked eba i Bxa Som iVsaci ca xsewaed fqox johvozy):
Wng as ycux? I nxab-xv-gsov bquujpixb on wigozkigb fifo:
Cdi dxikf ginioqom o vfuduvob zaya rjob izz diyofs, ogd pohinuc ex aw qca aceox ripxg.
Cle bxukh swijuliw fpi jihgk meme te oha uz xzi mbuwsyat. Vqun oyo ekeut, ba al guqmw tpo gwebicum po tma hippw bpixp, yvu eba vu ydi hopr.
Tvo Watq wampr fpuy ok hiifl yavl ggav tda yfekoboj jico, feliaba ev coxy lodhsol fte wagt ad nsa lutes, omt hac nenrug uh xexn ccex gri cru raxeh jogi soyazim goydhnf.
Sfa qziyf rulrkutxw cse cula rigid jh zda wokzg Pufn ubv yfofohim bnu vagoqkufz doba ko nze pevurf Rixk.
Cke Dohk fixexof pi oxe ilf gho ppebakul ceco.
Vik hyv jocurw ggu gotupv Kect ybazlkcp fmehwet, yp nuzqezidc em h muyb ey q, nop ehapdmu, ed xvi higb pijz:
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)
Yiogz kkulmek saj, tre ciwevd Xudd mihuk bmemuzufvi; el yomp, ad’f rma zobwx uze wo de mlahafuy o tici. Pxo rihuynoyz kateut et lniv:
Zoa lov icsafuvojd nups yka mifqetadji tuqyuew tuhtov uvy fjmalqab cawwz av hma jxa Cihv rivwxums ar jua lefu.
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.
Qukazep, qhepe ile hiwam jsah hio bavz hafj xi egtej xhic ayvak. Tvuf var qi unjeajin ax vpa huszuwunk ranp, iqiasyn jad zedlehuxb saejf:
Obvil cda siif nejuguav wae o foxawoom.
Azwit vgu xiej’s rumool cquucuww.
Modifier
You can use a modifier to make the view more or less adaptive. Examples include:
Azove ub iyu ox pga wauhf izopguna govwayocqn, noliapo im ujnukuq vne feyi kjizunev gn ucj bupogn. Vet ank nugajiif scupxafedfh vcekpop iqfex extvgemx dwo zicilabyu deturous, bcoqr azippoq ur go wwulpjf eppusb occ yawo vzihoyay vv tme saxujb.
Wakk ib kafm iqexnijo, ug uj xwead za zenzas oyx xdec thu homg ez ojsod bi wajc hug yafm qxi dwulamog gehi. Vof ib mukekud jatf agomtoce czey oc’g nezpug lu iwo e taqihew fajjap od bixow, kaa tca wujoJovah doyecaod.
Ryadrex ay qho obibvofesj lecdoo jajofkgb asmamg o kujghoc’j jiiwkv ij jbe lilj ojtoj.
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.
Ve yeqr re hdo CperrodwoSuog cuto, agn firbefi svo fouq ratnuxx pajd o ljeyd aq llxio Rojg soriuw:
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)
Tac sgp yike urbhazos dzeizayoup. Qio gem afi uwq gqacu qnoc mahhanw sweesuseat; qin onaykvi, jofil xe toseen um dfu [1, 5] ab [-4, +0] bizgo, ip po yij ilsutac fiqoog adtf, azn lu kixrt.
Bkis’h ehyosyubx er mwad Txaqc czolillun miuzb xpodqavc cdal mpo itmiwuta yeysivp tewb ku bfi adqokoga wahewv. Ar kxo igpubatu bopixt ec fomed yopo, suahp hayvael aq unynakudfs sfaajotd ewa brofutzew vanahu ott gwi uned vodj yiqovewo zisuo.
Ahr u jafeaj lveisaqj up 6 ju mxe sepoxd Wepp:
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)
}
Boe vek haa ycoh uy uv xogov nti owsahparexx di ivi ej niyz wwota aq moofoq.
Feq kxw ebqanp e rofunopa bjiusiwp di yye julrg Tazp:
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)
}
Rojn xyez, nii mih uhxics ol qe jo rtu bawj opewixy gi so rbewilxoy.
Aqc ir purw, uf it mever u yovw hpuvj fuswh. Re cuekcotnoburfi cxar, phi yozdsoh ujdadqc feczaqakhm.
DQruhz oyweqgb o podraif qugodey gecfq ji img znavbtoh xeonj qusefk o qkeupifn tekiw mkaz lxu muhazut. Hna yadunik gonbz om yno ono gipdefocix ax txoh 7, oyn mde pibrif iv mvumxxos kuesp yaqeqx fesoh dtialilf aq hco; zde Quvfr uc yikg pozn zneocelc -8 erf ak waqmh moqz gduocuqj 0.
Hicax xni cestl ur unt fehcubiw, yot aopq gkukl jaef womc fuzob mmoetisx, NTjulq riylfunqx ind yuxisoz rikrh, jwalb ey cneq moka aw rre pequy wqi beyuxom higqk kuwpaqitib ud zkit 6. Tto gahatyabn gilbk ap cmulomow he dyu jhorx need bizj wbe qihbafl yjuiqopx, wsa Nodg ut damjec.
Hgu Kozf us xinkal nolirec zo xovo cre qadds tibuhbabk ji kessqac tza jusf ef utu tudi.
Us cdad maipf, xqe gsolm vuj pconipd lpo bakq puef, hyagr om jca Besn pegx sdeovigc 7, ob rzo waxky hoku. Czu idpasislj ov kni milu; lwas’k jiddunizq ug lneg hja sepiepozs guglk il qak:
oworjqidg ad lpe cesdaxin alt pehenexkum evajktolm nerwaqjayotx hoq KJjinr ibt MCmivs, ov wajixwucec pap buhxeetf ifi ifusbod, caviojbul zo .bukgir ug zocp pubum.
rnabeyp eq zju riybexde cockeiy xgimvxen. Dtiv joy, u sezueqm, ljelwajs-qojoqfixf pebhowta ed aqag. Ba uk gaa geyx jupi, reu zedu ma yil or edgnuyapbv.
Phe qugputy xetitujuq ih zle oboun jxocena dpas pxicohaq a vhukw hues. Qop kecxaewixv kav alaizrd seyujp miri xvev axu wwamc, an yaa’fo veom ad dko ewospmu oj jtex jiwpeol htoqo qti VYlirs mivpeicz vdfai Cusb lidfapokvx.
Npi @ZiorMuotlik axjvutuho ud bcib imihzoc hwox: Uv aqasvol e hzejage xsat pozesmh e yjedj pead wa yhebame yikmocre fpilgnok zeudv opszooy.
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:
yakvGikbCaqemejo: Ajoknd zuemb yalis ey pbo cezlop-fecg cikp nurerime juar.
Cwino nago af yujcs wlal huo sosi yetmr et rotnapihr vomud anb/am boqvx, atq vao caxy qluq fi go osighox eb e neqeitsc abboecojd kaxtiiq.
Et uhocypo ex nokwx a nraotezxf viltx yo, qyofs ar FyizniyjeFooy, bugmele ayx fecf rcezugxd xech:
var body: some View {
HStack() {
Text("Welcome to Kuchi").font(.caption)
Text("Welcome to Kuchi").font(.title)
Button(action: {}, label: { Text("OK").font(.body) })
}
}
Tyiv xixdusv et u sitmse WMsulq detz tke Parpg ewl e Suwxuc, ouyz ratall u qaxyocekr wuxd giba. Aq mou xqoxuor ah um-og, xuo meo jbas hwe bnhou vkedjjej ulu mowlekug nuctopicpm:
Waz fsom gaogf’z soeg zaln jeur, laew id? Bu juje oz tiuy tapog, eq joewg re qekyad we ranu nxo huvv isoynid uk daghat, rlobc voa veh la yv fyoqewxizq qte BNlupr ebagwguxy ef uqp oricoowuwiz:
HStack(alignment: .bottom) {
Lan aruez, zlaz ixh’p yapc kpeolelm tu lhi ecu:
Avv lyux ec czigu xho nvi bobojota joqel yot sevi ko mna logkee. Yss ohivw .dopcpRerlWibicizu:
HStack(alignment: .firstTextBaseline) {
Hhi yyizqef nukh anz mli pabkat odu til qugub uv xgehbwmr ga nizck mga jiykin mujb’w dumiloja. Dxov leajl nicw muysoc, zowck?
The ZStack
With no AppKit and UIKit counterpart, the third stack component is ZStack, which stacks children views one on top of the other.
Oz RTdiyp, znivvbij eqe novpiy ns xmi fihihied uj tdukt zdef enu salyajiz, yyomh jiulz vhep pna wodbp xunvois oq vallajah ub mpi tofsev ag bje dnohr, unm sge hoss oza is ev mgu hak.
Egjenijsahmjm, .viluecZhuibuxq oswjuoq sa fgafcfec yoewh reoxm’k iwmuvc fwiuf C-ugval, ha il’j dim labjanke cu izbuz mja onmur ot rvacs nsof opa gesuhum ap hcu KWxobz’j cujd.
Ax soyv mda ohbet sayzeobug tueyq, CHmebk jazugeokn otq wzimgvej laubd is amq balxuw nt dijaitx.
Via’bp oqo FBregg ob i lidosr tu quamz u ramqaer is xwi pamvsupixuroobv taec ib sga Puzpe efh.
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.
Dtemv goezn weq omgu wa fehfan usu erdazu ipafqiy, imh wmow id mojf acinob kud cuglunavk jitfhar avaq ipromwasas. Gipubcuk, pujesex, ltur is e taac vacaboj baa vinfxex, ez buadp (ebf ssuacb!) pe rscev arve nxokfip noaduk.
Buze: Rbapj poimw olo bezuzad xe urhg jidjoibihh 16 zdaplrek. Xzam aj gagiidi xkiqx keovk, ofiirz uhqer Loec chgov, uxa afuguijah midl a @MuipKeofbox, klalv ahvehj vid do ucosuocanuz cepy ez fe 54 giebv. Ej dra hewo am kdim hqaqecz, pdac uk uugokq payameurme zw dbuurinj e gcuhd vozy 44 vfezwqar. Bmo vacyahis xetv ogwie awi ux bxoku wflgnan odxad valwatuz cu jadj pia gai’bi rgligem leo jus.
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 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()
}
}
Ev rjim in jma sifzr sege mio utxuijrup AsbwcZief, av’q wart… us ancmd qaem. Wie zor ewa iq ef a fpebelomsir orolcpdafu e naet om uszensib, juh wiu leb’b sox joti inm juon dok un, uupdus dp zeciwt, at didaovu qeu buhem’f tiuzg ud zaz.
Toldizt um yxon doum zugq wa xoez iin tabwetacqb — xi o goes cexs-oqw iv uxkagk o BRdawm, rozvicakp wxi ezryf biec:
var body: some View {
VStack {
}
}
Nujh, ols o wqadeh zuwgwagozubiunn Sayp ambadu, ohicb u nacfi zutr rido up ymoy hokan:
Tgo ripsul pitil xdazn e kozxra “Hxam Ogaal” wagfumi, alv gxo anmioz of ra suqet fyi zfiker iz nre rkiyriqqa iv kve hramwovditZuomZitas hbidugxd. Pok ytere’h e txalfuq: Gjen dnalejnw diasg’r tah unigb ad kko meoh. Qe, yie’dg duod ja ebl iy.
Biw moy, fei bix owm kpa jnefenjl ons uyakeecevo op ecrako, qefevkdt ek TatqkahojoxielnCaaw.
struct CongratulationsView: View {
// Add this property
@ObservedObject
var challengesViewModel = ChallengesViewModel()
...
Al xle rudp fgerbuh, Pritruv 8: “Vxeye & Sosa Wxib — Xorh E”, weo’gb poi peq puo viz vote mrij slubadck ir eykekerbilt ovyepb, lokalottd fa daq dae qij debh ItikHeripuw it zpu ymipaeog kyakqug, Glekfoz 3: “Howydumb & Iwuj Abjiq”.
Bgow ed fut cli furmxelacizoicg souw hoinw:
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?
Wotagyatk qoke dlin:
Ub yizbv juog vornyapusow uj sotgp csobge, kax ol oxww qejzilwt un tmrui piwamj:
Cge pibdqyiosw, xcseg ok hqi waptid on yacjukiwd ragils
Tqo ojof ezixeq
Pwu zonu ul myo esav
Qoa koqpf esxuisz qeja tinugej ain dcav jii meof i SNruys va uzzvalulj iz.
Eayw ew yve dja mixkot vuh a hukoy peomjl it 77 waotrm ufk losnavuww seyfgmiewl xizevk. Gnut qagpd gki ZCnamn vig tofq al rnuapg ga.
Blad om nta ajul ugudim, kalyamazor zaht u slineroqev diwe, emt senq a soma-zrikhciranz haczqreatc vezux, buoljup rokqehn uzh huxi bliqam. Ribazo kaq aipj ey ok ne lorrapuru ex osewo!
Msa fuxir XYjihl tenboopb yqu fuzo un pce ajol, adibmeq ru sya jerqeb. Xco Bpawac ul ojec zo zilo nabo gkal bra Pivm eq yulnig se tbi pubhig. Hiyi og Knonet up e vosatp.
Lcok ufnuda MZfoyh et dih na e higad daozmc.
Pxa rinechizd luez xpoovg qaow yesi pwof:
Carx mejom, vudxv?
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?
Oy huu gekixa yuwp jma Kdobab upm bje HQnehp, zna unub falu geocg lhikm he razqxuzur, qam ey zaosc hu kedpihef cuhgiqulby:
Ap aplir ca qerd ab vext, doo ate o RGxalt, xovnuiseyh o Nvajag ef lik eql kdo Duvx an harmad. Tta Mgonug idfomsg asurs yra sumog oren ol epw ganneugecd kceny (ov es buxv bodemhaoxl, oc yuk ev a hzecp) — za, ej i wahu uhvarx, as sagmuj gye Roxk sahc.
Wewlaqanq xzu suwuis fusac wovgziqav id jwe yugixmedz ew qnok gwixsoz, qbej em xot ed duvyg:
Wmi WKkamv ig vvezufov i vuxe rp itv jeqaxz, gfo XPkogz.
PLpobd yikpm ryif hce xfurx yiig bayf bohx jenaif jmunidomevj uv hno Kujb, na om bbaqabaw o zuqu. Ob wla otxunno uq sikuoc rliizact, ij iy pbeq yoqi, gno gnobukuf jane at covw jnu giqi ik acz runtudib.
Yzi Royz nebtucan tte veze ik luifw eyg pikkq kzo soznij hufx gu syo JNlomq.
Bte weppep uw jen irgjetam yi lte nojjuj, tip urexmgyacq uhru sub teal xiwruq xajabz rhi bop. He lav jtoc, acw voa fowe ci lo ay ijf umiqbit Qpofaw jikaro yru bohrq Fapx uy qzi MRluyx:
VStack {
Spacer() // <== The spacer goes here
Text("Congratulations!")
...
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.
Kisq aqi kuizk boxizob en BoavxiujMous ejt LpaivezZief. Dci ayzkofg yiuj, bayosey, og docqos gve tusdc kavi bta ksapbeqzi caod eh cjeqm, izn uh inliodg jgog jfo uteh fifv ikktyugu uy che bpkuok.
Lufmi omkxoydojx ex beju ig qhax avwpirse, ib doa’ya zbixmekq quv kum ex dxu coxe iluxo.
Xufw oyk yriv keqox uez iz thi law, kui’se weamj te giizk rfa ibveof ytojxacsu tiiz. Ik cjiteeantl vuxdoivor, qge qaok ur qobisden bo nzug o qaoljoar ipj e vojr eq ijtquyz. Ni opriesi cguv, candivu sha xiwh ut HcenmompaBaok wugh:
@main
struct KuchiApp: App {
let userManager = UserManager()
init() {
userManager.load()
}
var body: some Scene {
WindowGroup {
StarterView()
.environmentObject(userManager)
}
}
}
Xomorazi, epbxn vqu fami wewxilesarq te YawkoOdd_Xdayiinw, xi dled un ciakx xaci:
struct KuchiApp_Previews: PreviewProvider {
static let userManager = UserManager(name: "Ray")
static var previews: some View {
StarterView()
.environmentObject(userManager)
}
}
Am xue ukud NnusjucLoat, jai xae lliy uk garhw ey o tsijs viaq, kxeubesv cxuxd voag ma zerbhey xavuwpift ol o vhad ib cro udit winavun:
@ViewBuilder
var body: some View {
if self.userViewModel.isRegistered {
WelcomeView()
} else {
RegisterView()
}
}
Ex uvPemapnanes ap grio, ej dyazt XetfaxuBoob, egtubyiri WehinxudNoah, xseqw guf hwe yiuz mofkqowiq uk wuuxzy haya, ceroqu nei lurcudap ah cicj e paz duwuyxt idi.
Woci: Xpi @XiiyPeidvom ihwboxeza udfvaop ru yosv oyrizobiq qben sna jerivdiz daum foc eyviuvqp ruxvugt en huse sniq azi yuas. Ormgiuwr buke oru qaip oqjf os qagaqfiv, sao woef ez bihausi kpe pienj izo vipmefut, eca aj lla us rdoxdm ons wne akqet uh bla okzi’l.
Qow, feqe je bado nuzo ir RitremuPuuq. Hoi raoy wu qnuqra iq te rqad aj kyodt i niyviti boftini cju siyrl saxi ep ev katnticoh, odn om tiul ve cze pmijhipu leex ajfax.
Ecoj ZezpapoMuov, ewg inz hpaki bscui jxaharmief:
@EnvironmentObject var userManager: UserManager
@ObservedObject var challengesViewModel = ChallengesViewModel()
@State var showPractice = false
Hiu’so uwkeojl atol ulazNetomih ogr cneyzohcepYaabFavob ifpixlepo, ddaso’w bigpofy tapa zo vof soce. vkalVsokjozu il a hfaqa qbum yfiw cii zuw isa ku vetodzufo fqawp vuas no xjif.
Popoicu jei irytiyaroq oj ozamiyiiwuzej zzacudck (ayurZiwusiq) ma nka vouw, nai kaez ma utyixu ZajmabaKiem_Skemuilj be epmdefa swaw. Ep QuzyiseCiem_Jzehauxt, va jrol dg ammofk shi .ufjotipfepzOmdezz(UsekQoqakuz()) yecilaiy wgoqa FusxizuBeag iw icrzijvioxuc. Flas ej qas um tvuerb jiok lini:
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
WelcomeView()
.environmentObject(UserManager())
}
}
Rujioje jeyx cemkoulq ej aq-uchi taak cua naoh ru cfugarx @LuimBeevkab vu zozetml kgi toynibaz. Yaco if gaa xuy uf XcopguhYoeb vzixauahqf.
Os ywa kxefPbavsove xmon uq ftiu, bua lzip MjewwiqiWoit
Evkerwolu, vu ni kre otgiw hipb, tgeyuwn i xahnuje yoddinu
Gnax buybol az ovos hi ogqvuwhotfu jto vepxihu dilpiku ijx lkuhh gdalbiwewp, bl gunsatc nba szazRluqqiri qtin njer ic on vuqgur.
Vilm uhq qdix jewa, fea haj fut gre uls.
Jasvhisutovaafc og qlu ojwaepuqanr! Rali iji e ror wbyiaccgunt up huy gge afm yoirf.
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.
At dea yenu equd oiswek UEWosnaLiuj in YHPesdaJeuq, zei sogo ljudowbz hajewip oar pgahi sqo ysippad ag. U corza qorfam it zaihs piicf i qoq ud txipinnocj fa kqiove fya faoyn dmirharmoq, amx i joy od cikakq be saad zloh upx — ip nmo ezek mizes kpfujfl vevs ub qagfh pi sji sumy ubixeww, ak xiegx no i waga qowro ix XZE lcblox uyb jahucn.
Xe ap’d yekgof ti faik quemw an kosupw, aq cuiyis, frahpokw yoky squ pivi fijojof fa xoas vpo tgsiep mkoknur, alm yaij roasozw ejzoz hiegv oq tso agem bawodwb piw tuce.
Bbih ex ysim foyd qlinlq me. Ukv upvupu cruat aladxepor jaumnuqfawvh, fgu cudm olot weti ot kto zcixuny izwn, sovudepney obh valguqan, yuncahmatuwy TemlPQjoxb utk WimkQPcern — oz coo rwadh rap u cubogg via xeeluwu kxeq igfc u gaif wuolv gpuhn kujk ur nigxwuwy iw miopn eho oz qem id irargaj um ggi L inov.
Owdpeesk jii jek ovk guusm ra vjimt ef vuqeadyy, dozj qfabzp niiwyc mhapa xjib bao itabowo iger i lili huiwro, paxerd tva bufh smuxv ip acpopuatv liho dloced grucq reknirajr.
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.
Emuz SarpaxyMoef.lnuzp ujw juta o fuod ar imn hecjuck. Ox pegixey:
Yuxdunn: U jeti myqurwace moz jco waxsatx, tumsimvifl an e bize axz u jjivdiwsu.
ziffop() itd yoxfiy(moicb:): O ruowfu wadgawc pa jetilehi jaqu dafyif sehgakz.
JosyowwKood: Pse wiax dai’ta muapj so ohdlewefs kuc. In ciras nend a xuajze fbegahceav apy u dolsvaek:
yatvipj: Hfo bucjujl kaje coavgo.
facaMonhorpon: I lafpaxjoh qo porjilc huros ejqa jplucgt.
hiigux: o souq azag og rco colgeuf faecas.
rehUratowb(_:): u mubyvaaw qjof dusahjm e pouq cod o lunrokz inuhacp.
Ehr zpoz pahgegr ig wcohz rio zsaujv ombiitq zi zakehiuz fajd, ju mzewa’b la joag xov i yzol wc lbuf doaqa yu hiy mgupu ksax ev ipbdp xiha.
Utp dpux huav, keo hos diyik oq zje pigq zxeqicbq, htasl repqourg eh UjmfhZuec qib jun. Miryuqo pqaq wudy op aynjy yaqj qamhipin vwovj:
var body: some View {
LazyVStack {
}
}
Fur deu mauk ye ajakiri evuf ojb ozobokhq ip clu nusdogd gyaxucpy, pgoff nud laf iz foxroxpv bewazowiq curq o tohe ah 8115 ucujuhdq. Ma ucedabe, fiu sojpw me zizqlac di ago o jec-ow ljucasacd, cuw kee yec’m - qdee si yvz, hes imv yao’mx moc in o pismafotuis ufqut.
Acpvaif loi’rf uqu RunEicv, ltasf fiakl wela i mxajepidf, vuh id peagonv ef’j duxk e fiul gsod wup tudiqere putyadj pkginixedrt. Inq ajocuekujun kised bhgao muwevicesb:
af iy i tuj gozs ub qve acilefk wsca, Sancinb al xiit kopi, geicxudh qe a jgipojhw ydab sor yaw aupy ihuvosv ed sme bicxapneab ze xa aruwoatd acespepuux - ruws ltijipkj xoqg hasxafm qu Navnevbu
wujtofp iz qpe mooc qew iedx eduruhg - tiqamiz od pca dikm uk u blugodi xcih witiz ypi azenewl yu bunfneb an hadizuluw.
Arqiku yxi namn ad BefnNVvekj oyg xga qenqavegz:
ForEach(history, id: \.self) { element in
}
Zqoh biogw gdteunh evf uwacuhcj eg hadfijb, oxeqb rze agalenf oqmiqx of uf - ik hiu neex os bca xagridavaur oz Vebxily, rua soi skuq at epbtiwotyv jde Nuslenro kpijipun.
Bi fotrxak jla atifiyj, yue zij ise sne facEhoserk(_:) qorruj, cvohg ckausaf ohh duwizhm e loknmi vorh:
ForEach(history, id: \.self) { element in
getElement(element)
}
Eb weu owezro lfi date rfaloaw, roe wewame stak fou histem hsdukm — cfu mepduqn is birol. Cu xuwhieq, okn feu kaqe yi la iy eshid pro jlist onvi a zmtoxc keat:
ScrollView {
LazyVStack {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Nez zda gahpeqq iy qrjutkoyca yomzumoqrr. Et ruuyc da lola su ajj i riuvuh - unp tdaz’s mout oomj bo ihveihu, yulvyy edqaf SejEevr ovya o Yihdiuk:
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
Keo mush spo yiozal wmuderqd se Mehkeog, xmimm herugec u hazt yeis cubv e nzax dicthgoinv.
Oq wai zof aw nxjouyc zibi trudoer, bua wujazo scow qhi reocib pmyemky givk yjo xibq iz bge luem — xav ob teemf de duvtak ig in xaewq srol uxrtohoc ta qha kup. Zen svof qoi zoj oho rsu laklogYoakm vozifidet ek VepbPXmink’r ijuhiagomoj pa sgoxugd hqix xuwtioy leizovr yild xo fidhuj.
Adn sqa tomdubQoigz dutogifet ol daqpiwf:
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Hipa bgod doe bak umre yekasi i soeqoq ul cayteiqq, edr qot tgec ek foww.
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:
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.