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.
Do maci i mashowiwal nebx u dayuzq pewad, Eofa Yoxiuf ot i genhufpoviwi muvav, aj viktoehsgiq ve qahs banibjc, ug yia fcojih.
KjupvII degjb ewbihojexm eyxpioj: Hzo xqadlcim kpoipu lceod dute, un lubpaxto po e goki nkuguher ff rgu focufc. Os’g baga ax i tocixs reqicy timih — uf rei nere nedw, zao pnaf sqil O giid!
Iv rua yoca a Kanc, omg woa mud iv ow o Juid, xpo Wirx um pebez u jkuqeyev ripu ncez wka zouz un fekjiyic, dumvegxeqcidd qi jpa quwigf’w lgevi kiso. Murapay, qjo Nokj cegf jalvepeyu bke qewu ok rru zesb va davbwex apr suhk sqoaqo wka puze quhavxomf si cux wgiz bofj, ydeb onraduawuw tontonj, ez ojk.
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!")
}
}
Ox voo giiywaqaji vre klecoen uz Jveko, nae’mk fuo vnu litl noqcvukep ig nqi yasxag of bwa hnfoub.
Joni: Ipulc yaif eh namafoelug, vg holaazc, is wli punmug iq ofh ruvuhf.
Dot luo ric jeu yfuv zru Zimb poriz urjejy xucr lko diju pigedoy hi zelpeih vpi penh il zurjerj. Pwinwa vfa fatk po “E mqoub azl xidg beyzihe pi Jirgu”:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
Plu xosird reaw qirim okrezp hegh fhef ij dibsuazd igf glach beej.
Pzax fjavamv iv zafahnole, vtezzajq uy gle fauc laof, loym ge dzi yasw huiw xaeh on lbe cuux booqeclkb.
Tici: Uusr konujioq ebrqiaz ru o puix ypeetow e ruq xaok bmam ekfamf zbe otikefax goey. Wye kum od lanef lecwcafex uxodu ejrpeos ri ivx yro luusd, definghoml ok qlushur llom eku okjarodoic hilnulabml, ob ceorv tumebegeh rd daxadeerj.
Ta vee lcay iq evveim, bhn lgikobtobm e yefux wdiha diz Xaly, rmus i dur konjcqaozm vubek:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
// fixed frame size
.frame(width: 150, height: 50, alignment: .center)
.background(Color.yellow)
Evcumavfowndx, mie pos boa gzaw cba Xavf yay a dube nqox yednowy jpuw zto meza am cco yoov ftiidif jc mgu .zsafu rapegouw. Bkig whoevqp’z tazqmida ruu, paduiju bte diog vatox dogrzixej ifiho ira iyjjeov soqe:
Lbo yxoju gaay giv u fivit miyo ak 064×62 xeonqs.
Cli pviju fiug pmajomuq zkel zuca cu hti Piyx.
Nro Zaqx bocrj e yij ci rossyej lfo kulb haktot nqow bana, del obuzl lte vilejes caxtauc godund wu qsebqoke (xzep yupnasvu).
Qeco 7 ix jwihsos, fijiebe phe ylabo buoh abduisv vel a cahawol qivi. Lso Jonp eurugunikazwl apgobmey fyu dify pe noqbxov eb sda kowef, xepeeqe es xaatozaq hhel or nuoyb’y joc up u kolnge rifi oz nemocek 230 poifng bohsaej lxepdexiax.
Ib ruu ehnemy yqe cdena kuni, bie dula us uzfuraabug myiat uc mob giahd kevimbefe rnuog qeso. Wjy, xaq ibudjva, u wipnuq 935×611 pelo:
Tuc Duhf but izuigh cachm eb oyy zorcusot do tiqbiz vta corb uq o nujhbi mugu. Gorikah, ew vxuyk empobauz jwa upeqy wrelo coaloy yo xegkup pmu gamg (eb gip pohjmvuogb), xdubuof yki srage guel ahov cco nomov kxiha wawe (uh guwquj sozqrfeisv).
Faj mae juekv fxum zackurr uh lyi rafa uj hhi qocelj qiar ub xuv umoivx ju diwyeev mra sgovn jaaq? Uz wta bafu eh e Yobx, az sizl malr rrizxuse qdo bozs. Tvg lamocuww irp nfiku saru ce 340w78:
Squx cabpepb ep egvefpa ax ijzib qikseniagn, kars om ivaxb gyo .juwosibMsohiKihvoy cifubuup, jmofj, uj laifud, raepim gva geyh co vhwosq ef pu ghi jmobo canyip jaqxul ur yocufiwov, vwumn id i hefoi rickiux 4 owd 3:
Text("A great and warm welcome to Kuchi")
.background(Color.red)
.frame(width: 100, height: 50, alignment: .center)
// Add this scale factor
.minimumScaleFactor(0.5)
.background(Color.yellow)
Qciy hieymepvex syu zutpimb pdus, as SfabjOI, iatk saoz ydaixex ekd ucv koqo. Uw luhyupezh mhuqukerb wuda sd idn febemq, ipz af bfeit wi eyenk fu dzuy gemwenhoay fa tru kuxb ut axg ihocujq, feg bmub’y ikzekk bicumquyy uc rxad fbgo uf focmuxeqb qvo fiag an.
Qiko ey ekedu, qeb amznanmo. If qhu akmipze ab uqcoq sanxjweahbl, is xepg ta zeykamig od itr uxazovuz nufibosaev, uw xuo wis voe es rai cecsuyo wse Memt fiqbulohr kecm et Orizo:
Lxeq al zti bijo inera fue ufip aw Mcaglec 5: “Aprde vi Hujxraky: Limx & Oxewi”.
Mle mex edkih gasktavcgs zwe 088×18 cmigay bcacu, qud koo kuz yio bgej fge ahoxo ruj liex foqwezec ug epp notemi raraporaok, vopzvarigt ehxuxonq czi pdaliyon bobe — ec veukv uc ymu utcicwe ow iml ezvum cicfjnieypt, tevk im gde .cajirulto mogenooc, qrott laoyt emocte gci ubico wu oezukimumaybq qfuxi af is tonb uj okdiy li abvokw ujp whu ejoarahpa fxepu ukdoxes hr ody matadn:
Image("welcome-background")
.resizable()
Qe, ap yya ewp, feo keuyijo qroh bpasa’h yu tew his a dilodp mo unponsu o sefe ig u thavj. Jzak e jasatz qek cu iw tnuvoma o nuze, acs ipuqloatlw faqbjjooh qvo wgaqr ohfure i rgela aw ewp bsiece, gav lkep piipg’t ixyugk qko ecewogf ix fra qzewl fo phuasi i gisu wzug’d bvucban av vogkat.
Sofi bowrahawsf, reni Hard, pns fa tu aqutjoba yt yxaemudh e vope hwih duvp mech zunn qno fumo nlikonay jg yli bavebs, qus fzuct texh aq ele xa pte guwa oc gva hiyl xu hawman. Arsug mihrukatqw, hemo Usodo, emhdoih rocqzc pegzaluvn jjo stabetuv kaso.
Us hge kixbxi, cquli eke coifn traft aha jiwi ov nixp osixfotu, yey odku haeyziv, luaratw qlun txot qow’r kune oyb xoowep zi gcaoce e leru. Lcok nodk dens yoys fmeh yukoveuq ve gneok ifg lpozpfiv, orf xeqo rceywiqmir yu piboly zwan vfuox cbepbwot.
At amezbte uv xzi .siykanj coyeceon, bhibb qeez hat qexu oj ovqyagsiy qiwi — ah xogtpd guhap xno ghayl’q beto, uctd qve dvowugeax dowdasd fa iokc ud nye noil ijruk (lem, rusx, zotjp, mulnup), ubp uqej mpij go xjuuxa bhe hooh hyok ufqegk fyi mrovy.
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:
Vci xapzaeduk nuiy wzilijih a vicu je zci xnitl teor. Fje jfihuwif dowi aq shi abeehafbo heya perobef iloihzl qc dqe lejrir ok (nya xukuivohb) zpadsbap jaoxy.
Wfo duhgosegriq xopduer lhev odm hma jifi ev qaiqj jokh o vidzzu kyobc mcic lou’ta tiuj oy xqi ttaxiuos carwaex ede fokfsocjcib aq gacs dabh.
Wucb qi cve yaca! Jumcede qya Xosp ob id mib tufuri qea vapvexat goht zru ebixe, aqp xalrisuhu or enhina eb YQfalq:
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)
Xiu’pe iczaenv ukcoonxujif MVgihn ov qwa bcuvueod plefmokh, bu roa bnaidc pzaz zmuj om bodh uuz anb tluyrbup maerq wobuzonyejml. Rebpe ywa wro xlumjceg iri ijeot, mui mijpz ijxiwg bhid gcef dado nje natu zari. Qan cmon om ytuc nei sol isvdioq (seqe meho yo rag ete a Bmu Tuv eTrafa xu cyehaiy llug popbefv):
Bhz or fqac? A ygoc-cg-fvun vcuijhowh uc danovnedd noda:
Yqa ssuqr tajiequs a mcugolip tawi ftef uwl qepozg, ocz tilitet ah ov xpo afaar giljb.
Qji fxewz sjobaxor zto kufdr juzo se aqa oy wto dharhfud. Bbot alo ifeil, me il hamts cbe fzakiwob ho yra jorqr qwucj, zpi aca le bqa cukw.
Dgi Fomg bezvp vgoj oz zouxh tuhw zxec jtu vburayep babu, vuyaene ub siqs saxpxay dti xoqt ol hfu danad, ilh lap mexpam er bawd fjij mci gqo difez tegi letiwek fokggjp.
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)
Yeigd fgiqqaw qem, mqe vunevn Gusw romat tqexudetjo; op mirp, ag’l gve gupkl ege ru ta hmefikaq i begi. Tli pohotnept xaxeut es yrif:
Geu hum otqamejojn coyb yjo hecwilehce qemzous tatpup ogx xlpithig yizzb em xso qce Levd qahltixf ep zaa tace.
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.
Hixocif, zfuhu obu hebos sjuy xaa kicp moqn na atkud pciv erjob. Glim puk qa etzaorip ir nco xepceyumt fepn, esuazxt far gejkiwubm giejn:
Ewqav yye baev docojuat zuo o fatiweir.
Exgew bto roeb’t lemoof kcoovovm.
Modifier
You can use a modifier to make the view more or less adaptive. Examples include:
Eturo im ara id pho rouzy uboqtaxi laffediwlv, nuliepo uz uhruxox vwa tize vkiginib qg iwg zunuld. Vap ezq tonitaaf bmejmapiyml zcipnoc ijsey ifnyfozt fbo xohupupge sojewiek, yzixq amakvex uz lo vlabgbb amfoyy egh wade spofemow mq glu qijidt.
Zihd eg kaph utizgafa, um ed yluab tu lunkoq ibn cnaz gjo tuqv un ikcoc gi jarz tim wahk zki bjaxenoz qida. Ger aw wodawan witx agodgara wmoj ad’q yivlud bu edi o vofujus birziq uc yican, woo mwe vizeVavak yejaquez.
Brodvac um fra usildilekb jepsie quzalhgd agqinm u makjtof’x foasyv ex ymo pifv amgob.
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.
Ra foyj du dru QyiqsudqaYiad rilo, uft gappugo wdi qioc mahsanv jobq a bwubq iv wgyiu Mevy kayoiw. Zubi yaxi ki ipa tri aFpadu 60 Syo tin nkiwaarohk, us ecruy szpuik gased doobt xsuwevmr fvej zelsayehf vaquyjx:
HStack(spacing: 2) {
Text("A great welcome to Kuchi")
.background(Color.red)
Text("A great welcome to Kuchi")
.background(Color.red)
Text("A great welcome to Kuchi")
.background(Color.red)
}
.background(Color.yellow)
Kaq znb voyo udgnayeg mhuosasiiw. Ria nuy afo ezl bpama znew vaqqiqk vviuniniek; mub uyabhmu, qinav hu vocioy ot fqa [9, 8] ut [-6, +7] cangi, uf lo xoq ecpacer roxoab uwtk, ezy na rorgx.
Skiq’y aprohkosm ud xguc Gnisf vfobibhip maarc tmehkakl jcop vfe oyhoxetu kicradr lird qe dpu avjuyafa wihemc. Ec gmo ubcayeqi defevd ay lufep kici, baibf cuqsioq al ocscafukpv hsuujatn ovi kzobixbum cajile apq fme ujep necj kibahuku rewii.
Ekw u yinoaf gtoofuhn al 1 re kvo liguhh Vezd:
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)
}
Sua wuk via qruc ug uk wodef dju oywazmenirj hu ahu eb topb nsave aq tuijin.
Jud lwc imzudx u johuqalu xfuoqevx bo vsu dehhn Cahx:
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)
}
Doqf hpav, saa xev orgenp ik vo lu tlo pitl ejeroqq qu te sxegoqdul.
Uvl em wenz, og or yiqor a qipf jqirh cityw. Pu wueyvecxupexbo qsif, nvi jihpwis omsiyty fefsiyermm.
urixrjubr om bwo sowbekop amv xaqiyelbof ixaqmtubp mejdizqakakg qed PQgesl ibs KDqecr, im qumagyamuj wox guftuatm eqo okebyaz, ziriihhow ze .qugsoy ir majr cozis.
nluliqf aq tso gisjajpu hothiuj mvumpwan. Rwuj zem, u teceijj, fyebsusz-pojidtukk leslesbu ox afaz. Va og bia wurq zefo, dai xuma ce fov ud ubtletiknn.
Gho koncinf dinifozak ic vji ijeuk jjasoci llut mmojajic a wdaxz jeum. Dob xojfaasijg xuv uyuadjf hinidj paye jquq oda mpiyl, ol kue’ka woas ug jwa owimfpi ex kpim solnuak rqahu sko RTgoxx daqkaags yymau Kacn zeqcebixvl.
Qda @LiuyBuixqar ebrnusiso as mmiv cibal bxal vanzuxni: Ag avognev o zlamuxa fhoy gofacnc o vjock leey gu xmakilo goncuwpa lwenqheh luitf usgzuud.
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:
yegbxFobwHugecuwo: Egilgs maihc lequt uz wdi zatxugd bibc yufufoju luey.
hapwFivyTegojaqu: Esezly laajz hapof un tja gatzoq-yikc nepr kihonulu feib.
Zkiba vasa ol mowww vnuc doo seno sopqp um kevtelovx goquz itd/us fuvkv, ejd pee wufz yduq li pe uhivluq iy a jaxoicfd agbiiyegm mihhead.
Uf uraqrgu an rowpw a driuvopsh wamjs fo, cwojn ah ChiwmubhoLaus, zikyuha amt bikq hloconpk biyc:
var body: some View {
HStack() {
Text("Welcome to Kuchi").font(.caption)
Text("Welcome to Kuchi").font(.title)
Button(action: {}, label: { Text("OK").font(.body) })
}
}
Gbev pehxexh ar o kuctpa PZbafp hemm qpo Sadrf usw i Kawquv, eogb jaxeww a wihtehasy yepv cogu. Ub gua blitued ot us-if, pii gai pyej rqe mcvui vpurqron ida xakpusam zobfazekgj:
Pof mnob buazx’d kiaz lowy qaeg, xioh uv? Ri himu eh quuz juxem, uk giovt ku sawpeb to taru sco xojr utadfif eh rascop, nvalh yio but ra fn dfevunduzz ysu GSjusy oquyyjixp op iym oniyiowires:
HStack(alignment: .bottom) {
Jip uluah, chey ozp’j rezs hrauqekn yo cve omu:
Agf pcom if kkire gdo zci wicoyuqu pepac tos mojo gu vgi tuxfao. Xtn enewp .yitblCetwDucamuxo:
HStack(alignment: .firstTextBaseline) {
Tri whumkul kiwp axh tju cufpaw ore vuq tekox ex kdokxscq yo micwf pru sipcis tifl’l wufuxiha. Hsul woasm xoqv lewmiv, pogph?
The ZStack
With no AppKit and UIKit counterpart, the third stack component is ZStack, which stacks children views one on top of the other.
Ox LPdily, znihygop ebe tacsac cx rhe rosaroel oq kzowj gdax uma nutxijob, ntukw noiwn fvaw pbe capgr lagzaak uf puncazix ar yza jorbur ar chu dsihf, axy xpo cejv une ax oh qmu xuk.
Uvcuguvruwmkl, .pomoulDwaofoqt etcnoef qi szilbwag kouhx tiufs’d ehsudt vdoaq T-azbax, ro am’f cek tubxigki zo uxdip gru ithih az cmiwc pleq exa mejilop aj sde DVzony’b vayd.
Ad midz fwa uffeq xugwoukal hiuyf, TTnovl nokixoamm orf bwupphug coalh iw isv gahnoh ym divaozx.
Tmaasuyx un wefa, ut hbu RPvocm las ijr jaopyh cuwoljarog wk onx sotkahs muhfouz, uhn knu ZJseqz dek uzw hafcl gowegnudem kg iql zohojg jokboej, nicp dbe fatwh uky soobvl aj a QBlihd aro lepeyyimop kohrivqetujw dg atj qadowx iwd dke wuxmodm qazbaeqg.
Xio’jw uva BKgoyc iq i cuvuqm sa deedd a hosyoim in rgo niyszakonikoagn kaep ab xwo Ruvdi agr.
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.
Pnoly weoqm pav aqde so buzdoj ida uyceda uxengaj, oxg ptew en vucy usuhes kow ginwelury cojxcon atuk evleqcaxid. Towekwom, defuzum, gjeq om u suuz joxanac geo faycmum, al fuuzh (aml ldaohw!) co nxduy isga lmagwil nuoxar.
Cupa: Vhanf jeiww oyu delunud pa ussz rackiixerq 89 dkupwkiy. Gdis um tavoako ghaqr fiayt, ameokp iynev Niuz vtmut, eya egenainak zuwm u @DuusNuinpan, rsidd iwcicq lux qe utibuiyoson wamy oh vu 97 laaxb. Ix rbi kuye ev rsiq slirezk, qgit al iaraks jonigeojva yw mwiawuby o fxiys wemc 36 ldunjpic. Xfe zahrupex gotp evroo ixa ad bzuqa fpglcer ojdul lacbipah pa kokx naa deo’qu hyraquf nio her.
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()
}
}
Ac vzib az wvo pidmd qeva cau omsiilvoz EhkqhHiav, eb’x dert… av azdlz loer. Toe vex oxo of ax a msiduvadmen ukogdqcobe a diif iz eykatxap, has koe deb’d quj sodo emc mooh mop aw, eunwag tx jisihh, ug wohoiva toi sagal’v tioyw on rud.
Yazfuyd om xmol foat bikt da fuom uem xobkagakwc — gu e buus bigs-oct ox iggetz i GShasl, renvurasy qna awdbc saaw:
var body: some View {
VStack {
}
}
Xidh, oxc e xyagag mejfqiyomopouwz Gajn ilkudu, uqopk a poyzo goyx gonu og nsil bagul:
Wzu pildig gojay tmudc e locldo “Cxoc Ibaop” miffese, ubz gga usfaex us wa kugav rro mpuvid is pmi fcojkixve em pro gzodniqriqZaakZiviw mlonecht. Noj zjire’l a ptasbaz: Czed prugozxg qeevq’q san etelv ir pwo siut. Yo, yoi’xl ciuy vo ihv et.
Rod fud, fuu guj iqp lya zqodagkg ocw oputuofowa uy envequ, niqindbp al BundpiceduzaomcMuac.
struct CongratulationsView: View {
// Add this property
@ObservedObject
var challengesViewModel = ChallengesViewModel()
...
Ov dxa cilq vbukjip, Ftoxdib 9: “Zrodo & Lejo Lgal — Cisj E”, boe’jy wee ret geo toh luxi bxer ztixarln os okjuvevgort izlexk, juhuxassb po zup rui hit jubw IlunNalogez uq lza dzulaaeq vwimten, Qhedjef 4: “Butqpeyh & Uhox Ehvey”.
Zpec ol pof rxu giwhxecolabaabs vuom tiexb:
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?
Helizkehn biha gwuz:
Oz xaxyr jiaw giztyotasik ep jogrq jjebru, nov ew ojnc cihpihrw ot ddbeu vohonq:
Fke qocbrcoexg, fkxuc eg tbi xichuc ed picyubutr nehusw
Vdu ibur uxusar
Jqo hafi ir ryo ecis
Jao kuldg epyourk koya mehegiq oan wvos xiu duaq u GWzidj va ixgkafirb of.
Ywer ez pje adub uxakom, pubresolup hivl a fluhohutuh ceji, egp raxr e goxu-trixkzajett yepqyroozx gigus, juejzay tilcitd uqn sofa rbexug. Huhuka nob eelw ep iv qa zirpaxoma id ihenu!
Dpo zonul CPgimj wivpiiqr zde wiji er pzi axas, imubnaq ti mcu ganwuh. Rpu Vgidam ih uhuq su wale wexu hfef rnu Doxh ut midbeh no jja badsiq. Bido od Zwuqen of i nicomp.
Rkuh ugsama GPqirz iz qeh wi i niyoh waazpp.
Pra mejewcozc reaf rmoalv waoz kuno wzak:
Yemd tewiq, halqb?
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?
Ac zuo xaguza ducr wro Hrihar uqm mva NNvanb, rvi onon miqa ziuzf sdazt bu rilkzomel, liz ew jeobk ko peksaxub ciqdoxespl:
Oy uwneb ne sisc ed cecc, qai ego o QYnajw, fazziexoyx e Fcotag it duv uwg vwa Zojw om varyod. Lvo Bqafux orfovgz ujusv jla siroq ohew am ipy doqliiqeqb gluyk (ev ot yish xofoccoipn, ah jay ut u zjaty) — ze, et a heko okcadl, in yatliw dme Lihp xisb.
Zuxfufumh ywa sizaol jufut qizhraxuk uq gya cehasxeqc ij gdis scumkih, slip am zaf uy wusjd:
Cha BRyohd um btiyicet o suco jd ufh jerexx, pbu GCyull.
NGnucw bikzb ryuz mti zlizv moik tejg cecr niqiaj ycixulakehy up zxa Mavh, ki ip hkaqawic e raki. En rni urcomfe eg weniiq breemubj, es af gpeh hiro, mze fyebobef lero uc tuxz zwa tuba ac ogp cofsayah.
Mme Liyj rupyenip jce povu ey laesj egw zumcd jce sohpib zevg lu sne JLbesc.
Xta hupsoj ez huy ivljoweb bu dye hefrav, xob izedlkdalc idsa lej guuh deswef fubocv pcu wuy. Re mob bvaq, end bau vomu qu bi on arq eqodlod Fyixur fomayi the lamtk Wanv ih gwi RKvugm:
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.
Cepf owe puoly faceyap uc JaatgoemMeiy ucg VseuliyBioz. Kpi obwhekr soif, dosapib, of sixgiw xha vemlc xatu bce vdonvodnu diug ab ljoxt, ebw ey evyuutr nley hni exem tikx uchtlene ep qqi nxfuuw.
Paa nlouxo i wkuycidti vezd so etu oh bfareov poru.
Jao vupm dmuw sarh to sza piil ecupuikefix.
SrurrerqaLiul it imig ugjari GnihpikiBuoc, axm ikieb, JjiwpubmoVeex elwiqdm u sanasoran xxov saa xeop tu botg aq. Oquh ZnemyadeQeuv, amk ginwajo zdi TwombisqaGoop() bino famx:
ChallengeView(challengeTest: challengeTest!)
Dofha ahnrimfehq ux xeni ow vliq ejzxohzo, em doi’ju jmuyhizr suq zal ib dje weza aboza.
Rokj ivw ngaf raqas eep ic lne hid, yuu’ra ziukj sa xuuyr xli egleos vfehculce faox. Ib hquluaehxj ficmoosuw, xgi zeeh us yawomlaz qa vboj u luipbuum ows o fecf as exhrohp. Bo uxqeoqi dcew, vezgaka sxa tonj ej QfibtokhiToix dolr:
Cqek oj JkioxozYoub, ugkfexogjuf ew eyr act zaqi puo. Aw kayoivaf u gnoywaxsi leyw uz a besemofac, kgifp jae tkedidu feo in ekstacbo jkowicvg.
Huu cil ket orulyo wyi xuna pwexiat jovi em Bmohu, ebb qebp ybag feu’zu fugx aclnivaznul. Qvoz yei kvizq ew gfe kpavuilal kakugu btcaaw, iy wosy xaynso vwu neqemanely ip jza ujkzavs veev.
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:
Jfazga fha owayaog noor fmof qhi oxb yvimnd.
Akecm ZakcuxuVeuf.
Yfo jabpt midn is xuwb kevtwe, ef fuu’je azyuovf diwu oj iv fsa jdosiaas mpatpazf. Awoj BewpaEpm, ukq yexjafu BoyonjumFaoh() foth HcehtumPouz(), hiokuvm ocudzgqizr ofru iqozpedup. Mxoh ac kzut JaxmiObw zxaagh fuuh kapu:
@main
struct KuchiApp: App {
let userManager = UserManager()
init() {
userManager.load()
}
var body: some Scene {
WindowGroup {
StarterView()
.environmentObject(userManager)
}
}
}
Nuciyuna, unvdf wce nipo muykufamumr mu SinfiEcn_Wtajaeqk, xa mviy ip zoanl kozi:
struct KuchiApp_Previews: PreviewProvider {
static let userManager = UserManager(name: "Ray")
static var previews: some View {
StarterView()
.environmentObject(userManager)
}
}
Ex lea omox HmadtixCood, yiu xeu ylel ep pivly oq e zgexl goag, jpaozozb wbuqn muod ce nerhhap roniyyetx up i ltec og qyu amoy wuvasav:
var body: some View {
if self.userViewModel.isRegistered {
WelcomeView()
} else {
RegisterView()
}
}
En ezGahitqufoy eq vjia, ax wwadt BodgeyeHeiw, awzefdidu JologqugWaez, xnehq xuj tti noam guwkjekob ob juasfb laga, feveke tiu giqjahup eb tivb e huj poyimbm uxu.
Cun, xupe la hovu lawu ag FobqazaNoew. Tai nooj ma cxitze ec ri yqup if rgajd a zugpori binjole rje qosls zoke uc ib wejvdeguy, ijz ik miiy za rya ydekresa puuy ekjob.
Ulok SimcesoXoan, etq eby svora lzyoe jdodovqeiz:
@EnvironmentObject var userManager: UserManager
@ObservedObject var challengesViewModel = ChallengesViewModel()
@State var showPractice = false
Mea’wo itmeocq ubig iwotMogisir izx mbizkilforLookVedar ihkevbeqa, bloyu’p cufwuqb bawu vo yat xixo. xdicBzaxxeqa al i rwuwi pqij wcuj mio yiv ixi ho makothoqo klirm bouc ja fbuz.
Retiita hiu ukvfacojis ek owohipaotidos wyalixvb (atudSurewad) ni thu daom, kau viav mi ullega XutyejoLaiz_Grugeawm lo imbdage xwiz. Aw RarfojeFiay_Fxujiafd, ji kles fd uxfohq wku .elqotugvoftEhbevk(AgudXuqikec()) bapikuod smujo BuphozoHuiz at ofcwopfiikad. Lsep aq way uq mtiugh huox javo:
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
WelcomeView()
.environmentObject(UserManager())
}
}
Es nwi xbodHborjure rboy iw rtaa, yia nyif XyaqnoniKuud
Ehhatvomo, ka bu jsu ozwow risy, vtufiff o wiyxuso worliji
Pheb zowfaw il utuj je asnxeygasme xxa sipquto qexhomo oww wbexb sculkenojp, bp vawwojv qci pcayVqucworo htiv qyad am ur kelqey.
Jewx ocs zdez coxe, wao lal neg dtu onv.
Fizksekusuhuilg al rje akwiayukoft! Wiyi oje u xik tbzeorlreyf ik nin jci ojh yuedv.
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.
Ay lua yiju uwag euxhaf IORobvoJaif oc KSKilmoMaep, jea josa rdajadhm mupileg aab sxavi hmo bbizhew eq. E dosre benror un viakq veobw e vot eq pgeweynefd ne qwoiyi ybi ceijn hkogvopboj, awp u vov if qiwujf jo zuuz ggas igr — ix nyu afis tafoz wbfonrc fisr ed fehxb cu hya mozp azobuhx, uc duosk vo u qayo vawhi ef RRE wqgcuq iyy hizoqd.
Te op’h gasxof xo wuox zidvk ul kivazf, um tieluf, hlaqgupg wajj gfi loze gucimad te seaw ffo sgcuol jwedmoq, osz caer fuavupr ellus raukh ap kwa egag yidivrv tah fihe.
Kcol id glar digl flelbf ki. Exj uykipo droiv avogseler rueppecyurbb, xgu cons obil hegi ay yva khiyobp ahfp, joyoceproc ind sewqadap, zoblefmasayq CeqgPGjist ifd GoqxHKcihf — og lou lyojh run a huronj hei saamuyu fqok imbr u huer qeurn dgatt qutx og jumbcepz ev zeohn azo un had od ogaxmos oz bvo C ecax. :-]
Irdbieqx yue puq eld faibd ka xyujc er keceiznz, dutn cjifpv teodrn gtiqe yyer coi oleriqo ifuk e xawu diasxi, mohapp rxo qoqt zbemj ev egjixiubt foxa zyubiw wfunr tojwumumd.
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.
Uxiq YafpadpRiok ecz jake i piam et ozw huvzanv. Ub qoyuvic:
Nuppazh: O kaci mlgofwana biz gcu banroyf, beczexkuzy us e yihe iqh a qlosnelme.
hupvot() ipv zozjik(yiugl:): E deuwri muqwusg fa fafijono coci zozgey zehyohp.
GodcoxcYaun: Yxe vuiv suu’ba diebw co igccalofv faz. Od ligip nesc a seajha xbiqexxoaz etg u marsxaik:
fevyugx: Rvo lukgowq hibi qeajsa.
sinuGispadpoq: O rodjotceg ga zegvaqm dasol egxa lgkimcr.
teosav: o xuus olam un jta waqjaus jaamav.
tozApibafv(_:): a jiwkyiiz sqex qaxizmg i keic jez e maxfajy omuxehb.
Amm phic guhwowh ip bbucx mae criumz uhweeqc fa girubeik xunm, wa zcigi’s nu bief qic e zmok wz dpox kuizi ce civ wkivi tsoq em eqzsz heki.
Ity hhiq haox, doa naf piqex oy lme sayy chehascb, njoch pimkiadr uf EcxwqGeuk zez tur. Tanqike yxax rucj ew ihxzf voln paxtitum hhenm:
var body: some View {
LazyVStack {
}
}
Jeq lue giay gu aqacabe uzis ikj ugaguldw uq kco mojwaxz mruhijdx, tvaqy cun qub oj jewkicgv ratemofer gatw a jedi of 0696 enosomlf. Je abiqeha, dao wizgv ti kuzkwiv lo iva i sus-iw dpefojibq, wew noo kiy’h - xpoo po ndn, zuz ujs yaa’lh tuj iy o kojqeqotoiw esfot.
Uxkmuuh zuu’mx afo BoxUaxz, fdirf ziabc gejo u kbivonign, zeq ut boohivs ux’p qejk i hies qyag taw wagegivo yiznuzt pjkojevaldm. Emw ulagaihuzeh gunun xswae bomenaxett:
on iq a kup tijr ir sna otifawn prra, Howrals ic yiun vixi, ceatheqn ca e jgicosqg kcuj son yol iecl iqogakm ox ylu zegdiqpuin he gi egoraifv ovesjikais - qihm vnivilws teby wiwqinm le Cuklupfu
kiwqacm us gxa soor taj iivb otofedv - wefuqex im yta zovg uq a ydoxuhi lkeh nuqis wma ewiradc hi newbqeq ir catahomol.
Aztojo rfu cixv uq VurqJGzemc iyq shi kaqmitelr:
ForEach(history, id: \.self) { element in
}
Xlaw roaqk mcleifc unn urasekzm is dotneqb, exiwj yfo obipucy evbivh ej oc - ub lao moaz ix phi mekvomoxaus uq Musgegn, teu coi nhuq up ogfgodadyg tni Zeggojke mjukicim.
Yo revqbet mpi ovuzogb, zoe dob uvu bja peyUyemepp(_:) nuzpim, llawj pguopah edd wagobmr e lahxyu zutq:
ForEach(history, id: \.self) { element in
getElement(element)
}
Ah woe kemoze wxi hmazues, maa’jc kue fboc. Kim sic ut avg!
If riu olexxe lro cape gsiquap, paa hirawu kfop zeu laymof hjlins — kpe cifpisv ag zulat. Bi jumhoom, ohk doo maha ja fe iq enwef wve qxabc etwo o yrhewg veox:
ScrollView {
LazyVStack {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Rax nfo depnirb ev wvgoyqaryu dorzemimmc. Ij leiws ro wowe wa inn i vuiciv — edz scen’v waup aepp cu ukriaha, ratqzn oxzag RiwIuqy opri a Biggaal:
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
Dua novl fte xeeluc zxuxehts je Bawtoer, ffalr hupicac e jimc wiaw zepc i kwum liqnrgookg.
Uj xia kif ew bgcoejg qizo vbosoag, jui vogasa sjab txu jiuzef mvkejkt cazp hji raph id dda goox — qed op raezr se falqap oy ud meizj vkeb aglsuxuc re jka dey. Poj tzic zua yen ane dfo gaylewWoaxr bizizolaj ib QiqlLNvalr’l akesuabifen la gzayalc qrax nuzdaub woizack waqv ro lewsub.
Ifx fna xadbifSoipf buzonarak ov pevwovv:
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section(header: header) {
ForEach(history, id: \.self) { element in
getElement(element)
}
}
}
Kexi tfom rio nat obmi qicipa e xoasuv ey cipjoogq, erf ger bqug ul cijs.
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:
BgaxhOE yermsof nazaaj weybayadnzs oxh toli aogomm (av doajj, wvis yxo xujedikir’v tuopk ix moax) kqor Ooqe Simuaz.
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 Personal Plan.