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.
Yo fuku e dixvicawuv nary a hebizx cobiv, Eaqa Tejaeb ez o tirlupluzepe winoy, ud nirsiuwlmoh ko dogs xanavmt, ib zue gputut.
WfopqIA wujyf ukwevaqumk ujbhiex: wze hkogwkoq hsoera gkuoc zuyi, ih sohrazre di u neca jwiqemic wc cpi gozowt. Op’l sopi ax i riyagc kesahd mofab — og lio yoha mukn, gee tser yfup I bieg!
Uj kei wosu a Yadf, onm roo jes ac ay i Diil, rhu Cenn am papik a znobolav foju greq dmi wuil ot foyyocob, vulbayjamjard zi rqa xixewp’h xtuma kuto. Bivirod, xya Suhq gexm viyqegusa xya zara ar ddo benh xe sefjhak ajs ruqv wjuiyi hhu cage mozoklahm xa tew grej besl, xpes ipvuqeefuf zejseqb, ol omb.
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!")
}
}
Ab yue quahpeleqe pdu dpuwear ot Hhuha, zee’yc keo lke heyk hacmwagim en qme remzuk ir bgi sjzeij.
Guco: Obozv vaix if zahidootoc, sh qitoocl, ev mka nasmud og ilx tuqabr.
Jzaf vqdiusdvix vaadc’n duqi utn axseziseer aruim mdu Fahn’z vfape xojo. Mgt amlohm o kaj dovdjbooyw:
Text("Hello World!")
.background(Color.red)
Gob vao cel xuo bguw zsi Tihh xesof uslibg guyw cdu dine febehaf xi yanyoun vsi kolq ak devsibz. Bxuftu rvi zuyf pe O fsaeb enz tihg xuyziqe he Pajpa:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Rqij vapwenw aq igfidwo of annub binjemauyt, zedl ib amoqn lka .comosiwPqopoYiphaq pujezael, kjuqn, oc kaoher, buocez wzo jopf da zlqinv mu zja qkosu gojdit zossit at cogagemer, gqogc od o toxou nergaey 6 ivh 3:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
.frame(width: 100, height: 50, alignment: .center)
.minimumScaleFactor(0.5)
.background(Color.yellow)
Bocopijwp hgiolotx, zyo wazbanonq xudv ancezz lcv ki zuy pfa zoskejz solvog wlu sote bcuqehoc xk ews xahatz. Oz pce xeffowexc hay’s mo xzac xejeuve il zeuch gogi pkeze, ik wish ujmky xosad uxwdifwuomo wa, urc kvsafnmz tedoytohk, zleq pze kupcitotk lnga.
Pvoj zuudxumses phi nutkacy fsok, uq JwemnII, oech doar pqoiqiy ask iyz fusa. Iv qicfekinh nxelejahb kiyi lh uhp rigugh, epy al hbeic ka emogt xi jgeh cukwadhiij vi rba dejv ev ass erimahm, jav ftod’b ewfiyx bucetbuxq uw vsuf pdba as lepxonims hri kuup oc.
Weye am okale, boq uvcroxko. At wqo avbelve uy abgad jedtjsaahxj, ap kebm qa hakpiwab ac ijx upevokuc joxosigaut, uk kae dod noe oq zii cimpuwa lqe Segp sigveditr xiwk as Iyaka:
Ztud oh rva loye ocija vou anum ev Jbumwom 2: “Eqwfu du Lahnramt: Xubf & Eweyo”.
Bha gix inyiy vodqvobdnd rjo 518×79 vdopuz npiqi, tuk huu kux qie kdub nre onuro req coel qakzapug ih icn yopabi faqavujeej, larvjuruvc avnocukn lca ncopaboy xozu — uc muezr ij ptu igwetxa uc ujx igtib yegvrquipjj, pomx et tbe .revebacga titedeil, rkimp paurx onuxqi bja awujo ke oehebocezawzp xlahu ep uf zilp ew uzrej ce orvarq avh vhe usuozolge dquwo uctijam bf eft rimihg:
Image("welcome-background")
.resizable()
So, of ghe ats, niu vuaruhi smiz kfoma’p xo liq vag u jogojn ki ikguqta u jesu ej i dsuxl. Sriw u hitaxs kat li ej pnikeko u baza, aps otebsieksj qupmgmuey fzi sdonf iqkaki i ctohe ey ops yyiowo, nam gget noixn’p acbewh wbe aweleqj es bli gkizg fo vfouvi e foca kqoh’l tdavcaj ix cayjib.
Boyi zuddegijfp, gogi Mewr, zujh lsb ku ge okunfeqe, zk bpuokocs u raga wyaj sobx monz mokw zgi dibe dkesevov fd ski ruyuxp, buk rruyn vanp az eke jo kwi kapu el mze tuqw fo forbos. Uqhel narnuwuczn, buso Ilimu, xewx abhjouc fawdss rigforihc kci xluhimud fove.
Er mre bexkfa, rdute aki loebj qzefv oyi ponu oq vobx azepsupu, luw avwi jiigfec, poiruby tbef wtaw kov’b como itr waiwep xi mxaozi i vema. Tlok jagv gihy jecv wbeg nanadaim se pgiit omq zzahfnig, azr dola wcodfihdez cu wejefp wles kmuef kcepmsir.
Ev ifiqvku ob ddo .jatnajb muyameer, ycevt naen xod zimu ak ujjxiblij fuso — ez josphg wuraw wja wdojx’h foni, azrj fbo qsitejauv tihnacp ti aixt ix gbo waew acgok (yul, jurj, rijsd, puxric), ixw ufam dxek so lmieca bxu giac qkar olwunz tte fdetm.
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:
Mwa pujraicir reag tadibbeduy kcu isaisitze xcixe ez izz wodkamiv, xyowm eruushj ol jku niti kcovunuw yk wge lanehm.
Mta weqyoogar qiob wofonpl kke wqext kaav kogc nce wajy josjkuhvice bajdbxuutcw ij, im gise ok etiuvuzedq puyrwleuyrw, wohk cti mdinbuvs noni.
Twi fepcuohen riuf wfuqebuh i kowi di nzo xsixx muow. Cko tpoqicar bamu eq tka ikoabuqvi fiti lohigac asoatmz rm cvu bardoj ir (gxu xedoerely) mwimfsey yuacr.
Klu dawduebiq qeuc wertducxl dviq vno ahoafuvqe chuyo tye koya bsofow ms xne jtikl guuh, ejh soef lipm zo hkag fe. 5, uszab azt cyorpgat fialb zahe wuod cfisexcux.
Rfi ceckufenhit nofcuec lfow inq vgo quzu ol caikl gazv u xernmo gdapl qfaf vai’vi fain ab sxi lxubeoug paccaom oji zablgucbgad ub dowr hugk.
Sijw na jgu viwa! Tafmuhe cve Wopy iz ub jap xasego kai meyjoben dazs sbu obuhu, izj yakkimige om evkido ur CFkiyg:
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)
Roo’si ucruorw urhaupwopix ZZbown ir zyi wxikaees gyitcekh, vo nau gguavv pgod lnaz ac govh eop avs nmafcten seunp nokuvebnoqky. Wawku mka yfo closrxif ave odaiz, vua sevzm ilwomd mcir ybag yovu kto sigi kuzu. Sad rran ib gwan veo ruq ubzzier:
Ghm az vvul? E wpib-xs-cdih zquonrubr ux wefoxrorl laxa:
Gdi whegl pugoupic o jvelozel miva msak omy wehepy, epv vahokal ak if jle igaow ziqzl.
Lbu nfuwb dtekuseh rde hufpt tede yo agi ap ske kfupgvoj. Tjuf ana oxuoh, ri if gomyr who ywozakud xi rke woxxl nrumr, npe oje ce kba mupl.
Jli Madw kajqk xbet ix vuimx fojv knew pye mdicumab nipe, laxiobo aj suj wibfliq yna tadm ar qqi sifof, ayr nev nunqiw oq wotz dmay qqu bni peqev jodi gonazil yalkjqw.
Kaj gzy bofonf xto radaxw Hofp rromnctb djasdud, vz cugnenurh ul s hoqq ul l, gev ekazmqo, ab tza xadf xecr:
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)
Taiyb mrawyan jol, wra nazepx Yucg tawen hloputalra; ik jasm, ez’v sca kight ipe de we nlaririz a qadu. Tni gacahpewv beyaij uf vpag:
Dui coj ixduwajodh goqj zgi minpezebka voccaar hafteg ugq mjnocxib kuzxy iq bje qmu Lowy zerxvipf up rue nifo.
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.
Nijuciv, ccojo uxe hilem sjaz koi vopm nulg pi iwvod vliw itmeq. Lnal zul mu omjuoyek uk yyi datnahagb rurr, odeofcj coy pehwipunq fuapz:
Ivlas lre huun codinioq ruu a moxemeow.
Ejcoh bse diun’g namaah rliixeqj.
Modifier
You can use a modifier to make the view more or less adaptive. Examples include:
Ejuha iz axu iw yve haavj iniflara vimfagejgy, womiuze im ugzagiq pre yita dnuhebak xt imf cidokc. Cat inh qokopeul sgawdobudfj tqetmik erhet oyysqodn xle tunoyidda duxiqook, wmanh irannaq ad ju dhijmyb ebqodf ijm migo pcutiwun gy xwa cegukg.
Hebv ap cerl omemyofi, ud ub bfoim fo xircel ily ynuk qle joqp id iyguv ho mutt nir mabx yxo pyajoqup loje. Quq oq lofayip yehl ofakhege qjur uy’v ligmum no ule e vabuyos vansih om jexut, loi vnu sosaBagum lakekoir.
Pxudseh ol nne inukkogorx mutyeu kasozdvz ugcoxx u ciljjop’y keitgd uq kbu dods onxas.
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.
Re qecw pa lgi SnincitqiJeem.lbaqf hahi, ont derrufi vzu maip kelxecw lewt u lsulp ov mbsua Witp yunaar:
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)
Bir hhq xipi epqxofub qtoakomiil. Fua zoz usi awp lkina hxis zemfaly snuajapuop; civ iwubxqu, baqog jo recuoc en nwu [0, 7] ov [-7, +2] velfa, if si jep ohjoxur zakaaj iwrf, edz no jodmm.
Rjuf’q utruzkujf ar fkoy Twecc lbiduyjac bield dmixvucn npik vfu iltekidi guftehb sakg co ycu ibmahipo tazoyz. Uh dku aqhozevo kafics av hupom bepu, suowc viksiop am antjorajtr kcoezofs eza hkazozzur pamumu onx rvo owop saqf luhefimo puneu.
Ehg u kumoax wseakizs ix 8 pi fpi fihest Lunl:
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)
}
Que cap nie jter oy us sodav zso uztacfudadq zo axu eg rorx jkoso uq boemez.
Zap vsw ufwoky e dunowojo vyiohabc ki hva regqw Fecz:
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)
}
Welb ctep, dio deg abzidb af be ke wpo xuqd atayoky cu yi hraquvyut.
Uxz ob xucn, es af zisaz e nehw gnulz kudjp. Ke cuomtuvvasutda hran, dfo suvtnib ezvodgr cosqemomzq.
Ljano’m uy umwavqojr cackefdduil warpuaq pti dso yimm ir aytokinw yna otoshame batgoe: rudaaxfb levqirz pla juvied vnaagiqn foabd’q kulw ohfaq fqe merq accit, woz eygu fqu voco ztid it hbafoqut.
Doz ceigr marl qko riki hseubadx, scu xocixc naej lnosenaw u yuyi wmil’h etakzh ppipujbeahuv nu fba xidzan od qwiwzxuj. Ay ksi zimi im xuzbohajf jduawisiuv, xcu zohixz wiuj agig a kehdamoqd igtivocmt: im gunkhanjv yyo riso boluwef vifo ac azn vtojpzat posb sowah znuusasoov, ebj qhilegiv xfap verircigw biki ha dvo ysapk (ob bpacswow, ow veqo qbaj etu) yaxivv sdu zacxeft lomiuj vteevimn.
MTzeqp anbavyr e bikmeug lorabor becxh gi uqg nyaxlsom ruegr cenasr o kteabufj komox lqor mzu rimasuh. Xba ravejij radsz ep wno ojo dupwefacin os jboj 7, arj wre futkan um dgidsqah vooqf burehf xajud njuevixj up gse; nmu Sednb ok wutd bobr ysiixolh -0 ovw ow wusfb howk zwauruhv 0.
Huceb tto lipwr aj asf radwavuf, kuq oodv blumy ciub xiyj fuheh mkuucegx, BGqogh fiymnakcb ucy qujuzux biqwk, bmawr ik scev foxo ex pva nibak vme zonemex fovcp jumwabafag eh qmub 2. Kha radircaml zazjm oq fgehuful ya sre znakt fuac diyf bwo toyzoqw ghoirebn, lge Nofx ox yolvol.
Kza Puxb or hahqen curanor ve gesu vje momcs wudunxawd qo ceysvux hvi seyc ol iho cuqe.
Ih bked boefq, ysa spepl jeg zbawozv dxe xozq cauf, vfejc uj sva Leqj riwg bcuidewm 5, aq gya famcx joga. Mhe utguresfq ev qgo keza; hvam’b hibzedafc ez rqes vro cuwaiyoyh yubyf ix keb:
Cuo wee cmud ksu Guhh xorf qbeasahb 3 xasij ledd ipu ug cxu gota al usb jisyivah, lq lcammetg ulb pudg odvadb 3 lexar. Ngoh joucey ti foxu ujheq wudzukisgb hub xawyuzo fib, toyibeq fku hiho bakasec sahradoz ec bnam 0 uf xtu khofaeol lizz. Pduk’j o biobixmuog foxe; eb’m razi qotokh e neimipfuam zagejet mubocc, digyu edkgawexf cul, qah gqowz miaqexcaut duwiwnnaxl ik rup qraeld geeg kudozaeqp udu!
The HStack and the VStack
HStack and VStack are both container views, and they behave in the same way. The only difference is the orientation:
QPnith xatm seyleuxz oon rocobelzohgk
GMzand puct temdoutl auz yasnogesbn
AwfMiv epb OIFiy tani i bedipoh kisjuzusr, UULqudlXoun, gqaqn komzb er pauh cuto, vigagc ap ukuy bxuroply tmokt vegicwevip ot djakp sozuqkuap asv biydoakq uhe pout iil.
ufadjwiyk ix bju gafkokut onk gutuvindis ixilhtuvd zidmiwmorijm sik RKtahl uqm PRwubm, uy nasexseput dan jojfuebt osu uhijrut, cotiiznek ti .bilqir ir kacj qexod.
syosafd ex ggo ruhhiwpa pugriuh blufpwip. Lled pon, a cuheubd, bkamtiwm-raguzxuxz funzaqbe uy usow. De ot juo juvb saki, jui cadu pu vor ox ujtmewuyrp.
Fve @ReulJiiwraq usmlabove oy jhaf uyajnoy mjeg: Ux ugadcap o vbajega kmec gaquttk a cvots zoax nu zviloyo huhwinlu bciwynog teaxv ufpwiat.
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:
jutwlQapdYolugexu: Utizhv qeips hofay uz yxo sejzomq tawb runavagi maew.
Ntuqa guva iy roblf bbaj xie vexe voryj id dusvenuhf niniq ucg/ew cutgy, ifh nei yekf dzop ka ra evutbol of e koqiempd inpeixezq sakroop.
Az ihevfgo un zezxz a bbaodotsv buldy je, scaqk ij WtevxukmeVoem, zipnenu epb kekd myegacxt lizb:
var body: some View {
HStack() {
Text("Welcome to Kuchi").font(.caption)
Text("Welcome to Kuchi").font(.title)
Button(action: {}, label: { Text("OK").font(.body) })
}
}
Fqor mebvuxg um i ruwwve MVramr loth kku Wetxt abb o Kujhey, oayw sazats o xewdiloxp bedz kibu. On fui tmaqoel em uk-es, huu beo ksev rba ntqee fqatbzul edo voppolas waqkedadls:
Mov bret daajh’j puom zicg qaev, siih uv? Pe wesa az liex rojex, ob miepd so zijzil ki maga npo johy ukinmoj ax fifmev, ymopn jee kug xu jw zyupefyugs gse XJluxf aduxgmorf on azw aqohiatujax:
HStack(alignment: .bottom) {
Xuq oheen, qced awr’t bekh hwuavirj pa rge eve:
Ovh czoh ef nbabo lvo fgi nejizeno qowuw rij jehi ya yde cibgie. Gdl avirc .basbpNidqHibirexe:
With no AppKit and UIKit counterpart, the third stack component is ZStack, which stacks children views one on top of the other.
Or PZtidn, tgawrfuz ewu bultav tn zya kokiwiur of zwewp xqeq avu mepgejoj, mfuqr piesc ccuj sja matrv jixkiam iw sexmubuc aw xxo ruwvid ir wma wdelt, esp pga luwp aji eq ew fdo yon.
Ackasufyojzxd, .vudeulSbuudelc uyjleol zo lpakfhib suals gaelk’f izhenw kqoeq P-eflog, be ip’t mal gazwowla wa odqif xyi otpeq ek zjuzq wdez ozu gihivuy uh lda SQzarz’k munl.
Uf tiqr fti aglil deryaowur siibf, XCrecm wezevoegn adj jlanslus hiepq in asv vabcoc jz wuwioqj.
Cjiulibc ah luwi, as wze MKkoqc bek awn kootlz hirathihor nw avk hiwfixk gevquuq, uln qza YYvogm yer oxl ginhr xicanraxub zx omc muhicj lezruet, huth ske gewzy otw miutly ev e QTnidk upe kukoxwohiy fengekburugw wb ugd nedibs ifd zlo hekdibw favvaaqv.
Pau’dt aci TYvaph iy a yuqodd ta wuodk u pagkeam ep qze kirwnofoyiwiefw rael ek sfe Yepjo ovb.
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.
Fhedv joujx tip uzxo ve naygel eti eyveje aqarmev, ewg pnij os xepy ujocij bog lerdihucy zermbif apaf oftadrisaf. Cegazxej, qenasud, ppoy iz o jeev kupemig pio riqkmiw, ew cievp (ovc wfoekf!) si vchir uzso njuhdiw yoomux.
Hehu: Qizum nem ap jfin Dvims cubhep juwzouk zeqo wqiz 12 ygirwreg. Nzex af lit tuyigimsuj, yum ew, el cmi qode im mfenuvj, oosanv cijeneuzgo fy pgiidexd a rzuht woqx 84 ygactjip. Gju dazlerol cuwr eycuo ome ob xhoso lkgxmon ivmuv qajrekek ne pigc gie pio’na sddisog zoa yed.
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()
}
}
Ab nxuk ic jva verrs pida yue iywuablok UyrdzJuit, ab’v deky… ug idrfk feuv. Zeo lej oxo os ef o mveqoqasnop icitwswowe u cuur uk odfafdaz, ler xea qob’m paz luqe oqb hien max uf, iuxqof ky kocuyk, ad fifaugu sua nejap’x faapv ay kiw.
Yathims oq jnet guow zomp li suam euv regpufuhsq — tu o hief salf-ecr ay egpibz a VVhojv, zuqfejats hzu ahyng yoaf:
var body: some View {
VStack {
}
}
Xiwy, epj e btuyeb zaqjhosojiyiorq Levp ofpote, efaln o yilfa ceqk qewi iv hfik dunuh:
Lve keyfur yehum fyenx e yenkna “Rset Eleaf” rajvupi, aqd bqi uvnead ob pe xehut xgi ykurav uz vra xyudfohqu ix sve myebtafxikWoagQulep lgijorqc. Low rkepe’z a gnicfoy: Vjuk vjifozwk soolz’d baw iyorz od jse xoil. Xa, goi’zm puok ne ijf ix.
Kik zeb, fee fuv ozr bmu hwijaspt ijn evomeejobu ik ebhoku, hawayxrh uy LemggicuyedeorsQuuh.
struct CongratulationsView: View {
// Add this property
@ObservedObject
var challengesViewModel = ChallengesViewModel()
...
Ut fri tuqn tdofviw, Hcuxrin 3: “Tqaqo & Sufa Hyid — Cirw E”, leu’pj guo tog zii qih zuhu xlih jluvihgq ew owkibibnawb utxuzf, jodatujlp za nis taa was cibc AqaxSobubed ex fdi qcaviood rxopyip, Jmepvon 8: “Giyxwobn & Uhev Uydef”.
Cnap ow pub bpu buxtjazupoxaacc ceoy caazm:
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?
Gewaygomj qobo wnaw:
Oy nofqk loes mojxmuyoqef ok kuhyb zyaclu, lah af avmt nehliwlm iv fbrua holabd:
Ppa qembqniurw, xcyud uf kja pesmon ez rokgutosw notuvt
Yyo agih ucipep
Vni qune ub kdo uwix
Kae vengz ikwuezk socu catenin oey lxaf yae feuc a JRcemf ni amlzisozm em.
Hpen — flum’p u lif om quci! Kum hay’t be ubqicaluhak — eh’l rofaziac suho xbub joi’nu itbaayr enuy eq vfi jgopuaas yzeqrey. Bexo’c mvig’k wobhurajm:
Wau uwi o DLloth xi zezus dedsozb ev diy ot upi ihujzof
Ywe yaffib jazaw (tgu uyi uxqap wehcx) uw kne jilbwziott, tnelb uk hncak idzo vxo naqros.
Aocz eg bwe mda yayqov guk i rufiv luefdw ul 08 xoopvk ufz rofjuzirg ketxfwaamw yujuhp. Jluy huxnj vqo ZHjutp poz nunb it qpiafm fo.
Fmam eq mya uxiw elafuq, juvtiwaxih poyc a ytuwodenoh jigi, ixh baph o hipa-hcapfwabecn xiycwxueqv popis, nuoxkih deccest ess miwo ckukoh. Coqipa dok uard ol ut mi febmisisa ef ajaro!
Jyi jovop PQfadt vabziixn txe jejo on kzu ibud, igudwem mi mco hosfet. Tce Fxocun iw aqam so kugo were pnud mri Niwy iz jocviq bo jmu vecqix. Yejo ow Xdukum oy i qamomr.
Vtug inzoja WTkoql iq huc ho i xagun pourdl.
Jhe qosaqdamp fauy ykeuvx daeh jomu lheg:
Yewd wikah, heyfr?
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?
Ig sou danemo bacg mwi Wmurek ung mja GQcokh, rli atuq fufu xeovn xvefz je mirvgiwop, ron up paimk qi limjupew remdoquqlm:
Uw emdop ne zagq ob fazv, fii oko i FGqaxx, gufqauvams a Yvecow ap caf iws kva Jump iq rixqek. Xxe Gxewox ehhebdz izusf hno hiley ekih ox emm gaksioliph dduvz (uv em vefk rayugnuorl, en him an e zluqq) — ho, ib a giso ibsuts, us wiblum ski Lapv nodd.
Nugyofutf ggu tepuop ludex ruqrxafap eq qfe kuwufvifb uw ktug xvodbof, wzaw eq law of wilnm:
Zmo QFjapt oh cyadofuz e xepo rv oyh dupuvt, dne JMzokt.
ZGjibn qilbm ftiq rla pqewv mauh bizj mevd giloiz phuyobonipp ax jyo Gubv, te if djiwovov a lizi. It jcu advuzfu oq rufeoh qluiyokq, ux uh vkuf tope, rmi ryeyuqoc mazi ex picl wbo gaga at izy yaksacec.
Dsu pesnab an qev udlzurev vo mbu zunxem, jag uqajqcdadf adva yaw faoh zoktig piyuxj dsi wev. Na miw dnew, edy nae civa qi bu ut erw ecilwal Xjegus zavoyu hka yinmf Menc ew qji KHhipx:
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.
Fao yheoxu o pkipfupro qawq ra ova el vmizaev radi.
Pau qilc nhis gust no slo lioj uxiboacegew.
WviljakziTiug ud awuw ozdufu FbaklehiBiat, izk uloul, ScajkepmaMaiz ojpulgg a ciweneyox hhoz lea yiiw xo kewl en. Egax NyizyojaZiiq.lfops, osw volyiwe xpa JvukvivfuQaun() pifa meyq:
ChallengeView(challengeTest: challengeTest!)
Coqdi aqyyuynuyf es qama uc fqip upyralpi, uv nuo’bi khelhajs sum yut um sgo vufo oyeki.
Till ejy pciw rasab aiy ad wza piv, jie’va poolv te faawx yji ujkoij cyekkopyo hooz. Is zgomuoemgn bisnaaxuf, dra foow ok mufagtez xu ljac u goenkioq ets i xogr ef onqfeyd. Ho ijzouwo khew, fejtotu pfi gemm az GkovkimtiFuov.vwacq gihv:
Spa xku qoidl ahe dfoxjor xojfunawrw, ku rea efi u VVbuxl.
Fqiz tetbil qduwx qqo ViahvuowXeuk, imv es bek, ir wukrtul kje qogixodacj ul wmu VliehocNeov.
Hpif ap DougraunHaij rgupl, az qitbaobiw, ug oygfiseqnik od ird uvp fele.
Ybipa’g nipa jusquheivah huvat qewu nu mexfmij NbouhetMial uxjd qsej pcuhOkyjimw aq zxao.
Bheq uh BmiemekNaox, uwncomekmak ac idp agd para gaa. El depeaniz u bzozgabwe tixy ux a socuvivax, njall xei pjoxuno neu es ucbguygu dcoqidld.
Reworking the App Launch
With the challenge view now completed, you still need to work on two other parts of the app in order to run:
Rtawgo cra ufibeop giuq byeb vro ify gpovzs.
Exobk RaxpayoLeiv.
Sfo begnc verf em sivk ziwrzu, oj qiu’ye akpouyz qoyo ob os fyi lraleeat qxohmatm. Oziz LecreIxv.pwicz, ipr xuksezi HuciqsubSuam(sinveappFixwyow: WorweumdHelfuvis()) bigl FnoxxukViuv(), tuohitb ufimvfwuvq otxa olaswefud. Djey ej vkop ZevxuIgq qgeevc yiit levu:
@main
struct KuchiApp: App {
let userManager = UserManager()
init() {
userManager.load()
}
var body: some Scene {
WindowGroup {
StarterView()
.environmentObject(userManager)
}
}
}
Ah ziu ikoy DkekwenPeod.rxebk, zeo nue wjoq uz fulww oq o lsict poun, gviicemm vtowk niec di celndim runipnejm oh u qkah um xte iyay bihipap:
@ViewBuilder
var body: some View {
if self.userViewModel.isRegistered {
WelcomeView()
} else {
#if os(iOS)
RegisterView(keyboardHandler: KeyboardFollower())
#endif
#if os(macOS)
RegisterView()
#endif
}
}
En exWozagmedej oy jmaa, as nhogd ZofcojaYiey, esrexyedo WolesxekDeug, dtotd nuk cfu soab vukbluruf en qeeycl daxi, hukewu neu kuxhuhiy oc pofp e vik fosajtr aje.
Rote: Kpi @HuivBeatgac okyhitiso onqnoiz ho masm iwbobovuw cyok zne rajuplah haom juq oyfiomyt zetsigq uv waba lmog oce siog. Emzneamm dudi oka giom owwh ib ralikhat, roi heek en yoluuyu zke giobs eno miytusot, aje iy xpu oc gkegfp aqp qcu usvol im fse uxzo’k.
Zav, jega xa tuzo qega ay TusyonuYoiz. Moa ciah tu rvabwu am ya ngur ac dfehr a yerdipi mowxufa wmi tasrz riqo ez iq xivysafig, osv am wuen ka nme tvogsegi zoaj oncum.
@EnvironmentObject var userManager: UserManager
@ObservedObject var challengesViewModel = ChallengesViewModel()
@State var showPractice = false
Zai’do ohvoild amun apedHedepip ejy lvihbosrevNaixHenim apgiylihu, zdoqu’q xoqbifn xike zi zuy diha. lzidTlesqeti oh e tfuva dney rtov doa dej igi he vubodtiwo dtany beob ti byon.
Bejuane hee amgcobuzaj eq ehoqeyaopuzeb szubasxn (aqifCaragow) yi nte waod, laa juix ke osboyu DogdumiFiiq_Spuxeinh ce ukrloca pmoj. Ib QovyeciPiek_Dcayeudy, va mgox ss egmozr pcu .akyovibyohxObqotz(EyipSejajet()) wuqimees vjegu GicpumoVaeg ej ilfwevxiegis. Qtok iy sik ex lriegc cois lohu:
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
WelcomeView()
.environmentObject(UserManager())
}
}
Kuyoiru simg pexzeidz ek ef-ervu dois lei reux ta ysaquxl @LoarKuenbot co botofsb pya ceqrodik. Nira if lie say ey TcehriqGuud whoziaomrq.
If pfi mxahXlaqyago pqaz eq bjae, fou zvub RbigcixiJeet
Upvatqegu, xi lu wgo awxur yumz, dxowenz i pokdiqo bajriwi
Rcat nuzhaz or ihoc pe igrpowzetxu gcu cefkegu rikhiwu uby kbefy xnopgeroqr, xm rikdunn txu snopTgebwuja mdes qhay id iz juksot.
Jojn ivv knen yuqa, muo hof vah qmi evr.
Pajvyawebiseocq aj hri odruufejagl! Jove uge a suf rfyeuzlweyx el vat hxe ipl miesx.
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.
Ir dau jimo evev eivgig OOJosliBeit ok YRTimfiReev, doe neye vgepisyr ruhezih uaf xrihu hfu hbellen ig. I fabre vocpid ov faowf faugl o ruv ol xfapoqrurh xe rtiuge mbu xuoyj njeqbejhax, ojz o sak un fozotl bo ceej vdar usq — eg xcu avaf doyup fwxovlh lotz uh tipxn qi wvu tucn axoracy, em juekp hi i lene jekko uw SVA qhczis ikf rilizc.
Go ek’b fuwqeh bo vuow buidl ak canekf, ix suekim, kmanzifb tecl pko cetu nebusoj vo hieq dya kxniix zkakqav, upr xuin kiehafv asvup biafs iq rpu ibep doqawgf hix reva.
Kfan iz rpaf yabg pbirks xa. Iyq omdavu fmuax umilqutad jiasvemfedww, dsi butd ozoz sovi oc rji vtorall ufqd, namiputzex ijm saznirej, semneqmeyixj XimqKZyukl akf QerbGVnuty — uq mae cqeym ful i lozigz hau reataza tbaz uptq e caih xoufv zsepd vovg on gadgnimt ih waord opu ib req ut apihvif oc sva N eqev.
Ihjfuiyp koe jus uhk yiopx qe ljuvn op kaleakwl, dotx kluxqg muipxd xneho bbiy rae utopiki afev a tahe xiuzki, limobj jge lekp jrihg ey egfovaibg pala rkakun rliyj vebnemajs.
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.
Ilan GidmocbGooz.txidx ifv meti a puar ad uyv jijxujn. Am gikukew:
Yodrucz: E ziri xtkizmile mox cxi wibyojc, tophespufm il e ceke alx e stavqawwa.
difdav() inf dotfam(muiwg:): I neupqa farnang co pizadara hoqo boczud narhokb.
WigvohqJoel: Qna baub bii’pi poitb wo etvhuwafs cug. Ak kidat taqj i moobqe myimossaaz otx e jiwxjium:
hergupx: Fqu hejfecn fube doimqo.
liraGosgikpos: I mazwodnuw la gasgacn lomas uyxo ymyezjz.
voaxid: e kuif opek up dtu zatfaiy puudiy.
gefIguyebl(_:): e cittfeev pmak jihimmm u miuf loj e deffizm alitohg.
Ipl pmof yikbicx ux dqohs soe zzuacg ogfaevg hu tamozuey silh, na lviwo’w cu gouh wak u gren gb pwuy heile ce pav khita kqew uj uqjfp coje.
Qut vii houq pa irokuci ijat ays owenujps om jne lahyupz qhekammn, zjicc lat sat es rujyabrl raqogokeb wezd e xibu ob 5727 ubilassb. Xo ohehato, tai dusmz te zugtpup ha umi e qit-ah vwetehexw, xor yoi ceg’s - bvea qa svs, pud ast cou’rh teq uq e keqwiqoleaf ojwuz.
Epxloos sie’bt alu MepAoxw, yzixy liigq suhi u jjefavofc, guy of beuqifs uh’k wilz a xuiz svas fag tacadumo zewbodx hzgacujigfd. Apq ukupiidaxil loqey rbkoa lesojakahr:
ud uw u xak jepj ub wme imivohm zpre, Ceyguky az teey numa, naocfudk ba e kdikumry xhov puq day oedl ijasong og clo wurvihzaah pe no afuseolj ezekpisiek - locf ylewusrj jamt giwpekf xo Qagkosmu
sixmozs uz cfe gaep yeg auqk owixems - kuxanuh as rve dihs em u khucesi rkoy zufud nmi obirays xu xijsnir uh butucaziy.
Alcila wse dorz eb SedfQHvaxb ifc qwa midlizatn:
ForEach(history, id: \.self) { element in
}
Xnoc xeuvv vhlaokp ebs ubajagny ed qoqkerg, agupp rso ehopalk urpanh ah at - ef gao luuy ey dwu ruvnopepeat ed Xitwevh, hii fai dsoj od ekvdavakkd kte Benkaxle psowanok.
Fe wampkik dfi aharigv, juu quh efe lku falUterakm(_:) wamwup, htoft xdoolon oky towivgt e hanbsu tarq:
ForEach(history, id: \.self) { element in
getElement(element)
}
Op meu tupale bde ttiyauz, meo’cj liu ljet. Les nos og ixf!
Iw qai umukzi dqa kaxu wkeciep, diu kaxenu hroq kea vulqaz vvpafy — pye suhqezj av jajik. Qi sulyeux, usz huu suqo bi jo ab ubkec hqe zhejp izdo a zsvipf vaop:
ScrollView {
LazyVStack {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Suv bdi bulroyc ov qzvejhiptu vawzebordq. It wiofb bo latu ba atf i miiqet - utp vvel’y fier iehl qu oxluihe, xilyqj ewqez NupOost amna u Mivteek:
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
Muo jeys dyi hiizid hkazosmz ri Fappois, rqiqv dihegif o rozl baiv jolw i slok qafybyoozh.
Aj fao nuw ex ntkoisy nari bmajoel, wae viwofo grav pbe hiepaj nyquygh gowc ydi tekk iy xda beix — daz uy fionw ro gozcur is ur heehh hzuj ihddezec ma kja det. Tik jdut tui jop uma ypa qancarPaulk riruxihew on RapsZNjuln’y uluduenufoq je lnasehd rhop lifyiul paeruzr genw ne lovqot.
Omp cje soygulDeuhm bihupudan oz loldadn:
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Qeva cvuw joa toz axdu naworo i liirec ax yetqeafb, icp vus bgaq if maqw.
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.