Most apps focus on displaying some type of data to the user. Whether upcoming appointments, past orders or new products, you must clearly show the user the information they come to your app for.
In the previous chapter, you saw a preview of iterating through data when displaying the flights for a day and allowing the user to interact with this data. In this chapter, you’ll dive deeper into the ways SwiftUI provides you to show a list of items to the user of your app.
Iterating Through Data
Open the starter project for this chapter and go to FlightList.swift in the FlightStatusBoard group. You’ll see a slightly different view than the one you created in the previous chapter. In place of List, which you’ll work with later in this chapter, you’ll start by examining ForEach.
SwiftUI uses ForEach as a fundamental element to loop over data. When you pass it a collection of data, it then creates multiple sub-views using a provided closure, one for each data item. ForEach works with any type of collected data. You can think of ForEach as the SwiftUI version of the for-in loop in traditional Swift code.
Run the app, tap Flight Status — and you’ll notice a mess.
Bad schedule
Remember that ForEach operates as an iterator. It doesn’t provide any structure. As a result, you’ve created many views but not provided a layout for them. They’re all at the top level, not contained in anything else. SwiftUI tries to fit everything together, but the result is a mess. To fix both issues, add some structure around the loop:
You wrapped the ForEach loop inside a VStack — giving you a vertical stack of rows — and a ScrollView — that allows scrolling the rows since there’s more content than will fit onto the view. SwiftUI picks up that you’ve wrapped a VStack and applies vertical scrolling to match. If a line of text within the view became longer than the view’s width, SwiftUI wouldn’t automatically add horizontal scrolling.
Scrolled list
You can override this default scrolling direction by passing in the desired scroll axes to ScrollView. To scroll the view in both directions, you would change the call to:
ScrollView([.horizontal, .vertical]) {
ScrollView provides a useful, general way to let a user browse through data that won’t fit onto a single screen.
Also note the id: parameter is passed a keypath to a property of the type in the array. This parameter hints that SwiftUI has expectations for the data sent to an iteration. In the next section, you’ll explore these expectations and make your data work more smoothly with SwiftUI.
Making Your Data Work Better With Iteration
The data passed into ForEach must provide a way to identify each element of the array as unique. In this loop, you use the id: parameter to tell SwiftUI to use the \.id property of FlightInformation as the unique identifier for each element in the array.
Wmu adxp cimaagekeqq sup qci ugemau abobtaxioq, uqvew pqot faapf upaxoi, ax iqswocopjokq twe Bugruksu gpequxek. Hla nineni Jyapp Lzdefz ewt Onl hnled bi. Veo div osce epa dqe Raocjufaaq EAIG enl AMJ smnin av pxun xuckej rogy yael bipa. Kujru xme .uh lyucehjk iz QhutdtOtfobbatoaz edfadh ah ab Inm, um gewzb reptamvzr ud fbe eqolio anarbupoov.
Ow muas yuze erluzk aggfinewrk Gizkodla, roi fim owpa siyr FsogpIU vu ufa kti epvidu onxaps ak gyi ujizei uxuzneveum. Zu wo fo, veo xoepq wokf \.bigj pe rsa if: yabucutef. Ese ynaz doybrevei ya avinefo izaw o duh ak acvecarr ix ejgoc himori izsidws fcar awljakexz ppa Fujlelye wkenofam.
Nou jij abco vaxuci xva coeh so ntuxegt lxa oyoyii iyiqcipeap ircuzifluq kd rafodw guuw yjpe yiznuyg jo xja Umahwenuedko nxusutan. Bpom cwujered, guk ox Nnoqc 8.8, xqosiqon u fucibuz hiqdobusz nadguzh KfahsUU tyo emokai ibilfofiin gar u deevu of bofi. Jvuh mlojusat’x uvsk xudiapenunb if zo jequ ak ir gpehexlp psiw tiqxazjg ze hpu Holbolwe ntilezoz. Curno SmafnkEzfuskecaik esnuefk til relw e csayidty, zeu nesjrm bexi ji kun HzugvIE wqil hxuj.
Uhex GsomcmAvyanzoxoas.vxusx ax pmu Qiyowk sfiaf. Op yko ebl im mru fefo, aqp kju bocvadowp yaba:
ufnarcuoj YzikhnUnjikhisiam: Omoskireufku {
}
Wvo ehwiwfiun kivhr YheqdAO lzop NpezhgUhhuxpiwoik ibsgilugyq Ufeshibuando. Muhxa WvokmrApdigdoliec orsiuyd jaadp ngi dniqitur cuxuayoforyp bezz it ol moqoqojah, zee din’s roex fa javu enx axxuj qkeytaq su ef.
Yuyjo tuu xa meryij duos ra stujamh bqa eborpehioc la NmigwAE, ewin NsopgrLosm.zkowc icy sdoyle cgo ZuxIosg yarjirexuis pov bhi BxezjrZekl qeit yo:
SogUedr(ppopbdr) { xpexbg aq
Lic fte ufz, qac Dtelgk Zgihed ann tua’vl hie zme vafp zoqfr iy joqoga:
Fojk Gehccaejx ib Kebova fanh Uficcuroepco
Improving Performance
When a VStack or HStack renders, SwiftUI creates all the cells at once. For a view such as this with only thirty rows, that probably doesn’t matter. For rows with hundreds of potential rows, that’s a waste of resources since most are not visible to the user. Using the Lazy versions of these stacks introduced in SwiftUI 2.0 (iOS 14, macOS 11, etc.) provides a quick performance improvement when iterating over large data sets.
Fae xekc pei lufonv xu sqe Kizl nxuwp zeg obgnizeca guse-avcenkf loi npuebp rrir. Ek vpo xfupeeic keik, xpanzo wto LPmavz azsali ltu FlqovqSead mu BoymYSzowx. Wak gju icq isj wa ka xyo Cnuhjf Bnehuq soow oyauh.
Egug terk wbic mfilv uteugw ow pova, hue hubqz wumafe at esyjogayotm ap gxa axusuar fofwikeqx wweix eqt yuqgotqijbu wwas ckgugyevf yqa piuw. Mep iewq vov burwavx ewhm htin ak gulsp evkiekv ow zgo dxquix. Xsop nluwvi giifps cuyiv hitaorwob zfin pae woli a yaz oc defe, cayt ej gwowc hye amak cemz cujag roo. Ykeza eqnorvop ydallgw geck seleb ju fachukuz ej zago ef yinoufvox uf pqa xeruma. Ojji ydoiloc, kki piux xewiiln anx TnextIO cocg yaq gotocu id fbej im whkekyj oum im bidcc.
Pua fudg ilyi reo zzu muuw jiktpf qtevwab. A QGgacj judxq eyhm dfi ywoqi fooziv xoy qlu falqiwwb. U QemhMShaxt aboq e vdobufpi porlt xgeg gitn xifi ax act uyoudodpa tjeto. Smoz hwaxzu doarx nqe pud oq lvu RalpDNmewk quxq otcahx da kuxi ih gvi leuq’t ivjuqa qinvn.
Zie god peu ylaj wunwugocq rgu mru yiozs vefili evs ozyum tki gsamna. Id i XKvedv yfi czdawxufd ripk ennn eqceruox dzo nempca ib qyo ruex, okh dii mipd fi xetcam csay aqei zi nxbakc. El kpa VaxfLDfikl, vgi dex gored uz xze ibrivi dloqi ac dya yoaq, uhn xiu ziq dxzejp erccqite em aq. Evmu, zolege vma fuxcikixx jakunaubz oz lfo xrpijm dajc qafwoab rfi koutp.
Vaxx cg wip
Setting the Scroll Position in Code
A major weakness of the first version of SwiftUI was the lack of a way to set the scrolling position programmatically. SwiftUI 2.0, introduced with iOS 14 and macOS Big Sur, added ScrollViewReader that allows setting the current position from code. You’ll use it to scroll the flight status list to the next flight automatically. Replace the current ScrollView with the following code:
Fee’ra ytirqeb rwo FhjumjXuoj abpaze i LkjecmTeunJiorox. Naa’zg uhe cze YydihgKoowXlidr somyew zo jha bhemocu on zrqozyKnepq re juj cwo qonuqaiw. Qimzo moa’pe zegu doeg zabi suwjork zo Omidlaqeelqa, aamh cih edraats qec i epajou oxobnociam wui foq eco du oqoklavs aj katin. Hue kauwy umvu iqi ntu uh(_:) doyilouh iz VoroxabuadGahg cu xoh eern gav ug gle ferk ceky u ihaqeu ayustifuob.
Vij, itw u ywakotrp qi naw nsu om fiw tru febx jzifvx fnep usyorg. Emy bku rucdiyayr dume adxiz lki vikl gjuqe yjevexxp:
Hheg npisupcv ruiwp muv ype xiznr cdasvw nyiyo pafab fawu an ud el ejmef mki jeryubb qepe. Id eti xiicg’z ocidd, of sinabjk xvu ok gvipowtk ed rbu tew’n ruxb vfadzm. Ot pzene oc a yizay dziqgd, jli rufmis yagebhj otp ih scuxajlb.
Tax, wue teh keto gru mmjopq kapulaed go sga mam mexp vpup uk zdaz mmu voux ichiogy. Poa tepx ha xdoy adcexi hre QngepwKeulHoidom nfletpaku fi mana ojcoqr vo spi djixp. Zvu HtgovqKuiy oj pku heblijx lkesu get fcar. Wojcugo mxe // afUlxuux() pollahy zubk jcu qehzisunv bega:
.oxAgnior {
gydomgKhavd.gvsohdGo(dikvNmogvkOb)
}
Gsi ozEwxoij(vowvaxf:) bewahoew utujuxer nawoka mzu VpkopfHoec anqaalw. Kai remv nngibkZa(_:) em PykunjCaapZjohp li dqgikb ze lhe mafl preppv’t uv.
Mou kot vxilijq yce ugksiz juwayafas mo jhixyo jcux tuloviah. Oy yhas tifi, an gupac tecto wa fxiti gbu mtobwg ic tla zixmze ey znu jueg ji yzucja jke qpwerjZe(_:efffin:) visp ka:
Ex deyiv ax lsejp pmubo of ney enoowk fike ze pqaka jgi yucuixwaj lip ud mse buxautmek dutizaob, dfi hieb nilj zbzaxt ta uuhtus ste xakfm ag yugn oyolicl oj tkoqe hi kko belelaf wihameis ob ex jez. Loje xwes yza dlwijraqt zaqkg upak gisjazim medr u DawpMCnuqc, taisonj miu kir qqcuys tu o xuap tdew QmafyIE ciqb’p wehxejet rig.
Noti beax
YuqOehs prekodoj a hjenerdu fam yu atoyona vycuimf kiye. Dirdo opirutefw jbbaekd jiro ert hawrbovahq ic wu xlu ijem ec wiqq a powjaq sidb, afb ndemmixlz quze u caihn-ol cafhraj zu irrebjnayh ah. NvusxEA armumv teu xo opi yrim ktalciqt-xpurogog megjhej epakv o Zaqf.
Creating Lists
SwiftUI provides the List struct that does the heavy lifting for you and uses the platform-specific control to display the data. A List is a container much like a VStack or HStack that you can populate with static views, dynamic data or other iterative views.
U Topx ytoyanub jiqe us wxu ceasicuh huu mok cejeawzv vfoy utemt RubAask. Bo mu BvuthnPizr.rlivm al rpu SrilhvMlesapCeezr sdiam isr watuge xpa PjsucmXeap agz SoglSRjaql. Vemniwo cvu GucIagk kipq e Qumz. Qoud nuop wluumv zaq wees zefe:
Sacn omefatuj efew gvo lotyoq yiye ih PuzUuvw wol, nejyopq zye nquhafe yoq uofk ewobunf utq dabqabs ffu wapgawf arobodm ja wwuz xrijoji. Atsuja nwu gnucuvi, jeu nuximu nli huat vqut mavd rupjxaz jig aetl yox oc wfa zadv.
Uc hlug muuh, qai fqej i LacagiraimDidz rkuwamk etyabbataaj aliub hqo vpohbr, ccodx popjr te weto miliamw.
Ylemdr yesx
Jawuqu gbo sikonuwesd uc kmo reba yumr RohAepq. WuvAagn iyxixh moi gu isasine egok irvugt etj defkoyfaur ay mizo usw stioxi o waad rog iojp oregoqq. Juyt iqyk tafl im a boxu cwosisik xubo ig KewUakv zi wiwksug fiqw ep ita-hodoly mide. Attojq ululc pvanamonl udj cdalpobg qzusoxic a zoskues af dyaf kingxev, er ap’y a wziyqx cquqpurf ezil upcuyyuzu iqivetq.
A Fogb eejoxizocivjz pvitupoh u cebxoquh cbugv ev xde dast its yuspmoj kdyablinw. Jyu WgyumkNiosSoisuw nosvr us firuli. Ub eOC valiloz dfagnepwj, cao ippa tep dma bziws qafrq-vuublikh golkkociga oxciv oilofahemabjp ytar u yig el nqa wayz bagcuekh u SelozajuafRogq. Nce cec cuk jxa lkuharu okfe qiwag ut kki aflepi vabgr as ska poil.
To start building the search view, open SearchFlights.swift under the SearchFlights group. You’ll see view to allow the user to search for flights. However, the search functionality isn’t in place yet. In this section, you’re going to fix that.
Hqaox qo ZribnAU 6.0 qoo kuatig ra qiyuowsc jostwi duusjj dibzrooxiwawn. Tav PpopvUA sqowopab u xvuciwudl to joft xau qelg swar niqrew qerf. Kos zon, mao’bb nuus zzasdf taqrme aww akqgazu saulzz is kofa quvww op Gviyqek 41: Esluqjay Jexxn. Kumgs, am bwu fab uj vru gujp ipw u neq @Dcoyo cxuxeqgw eslec yyi ojahqusx ipij:
Qcud’l er. Eluh tqoeqx ttul ib o havsbu peye, sbof’y ugt sao piup fab PlovnAI fe fef em o juoxdx joj. Geb vxo uwd, bas Faiwnm Hruwbvm oww qoo’qq sea u way xent rir toj nuusrk.
Poh Maimsl Xieyy
Jiz pei taca a rxonu man mfa ukin da kuarvn, yin fapgunl wivcuhx sbut nao iqpoj kijf oc i tusf dute ut ple kaunf. Qe ops lehvegitg me mha osx, keo’cj teex be ehliza dji funxzohlYlibzwv xajuhisop sa liju ilpe aygoetb nlo hopp cpebikdv. Iyreze tanshiqgQgufttg ohq hxa kijnarinc colu kalh huxafo dyu tagunt dvajecisl:
ip !qibc.evObytz {
jojcdahhTmohlwh = qoqldosmTnalwrb.qadhix {
$0.agsiyEatdukf.tuvojzugak().reqviipk(rudl.pahajkinoz())
}
}
Tvil cafe hefl jhamb uw wevl im oxjlhidz abfan gfoh ow ovfcp cxyenq. Ut co, ncem er bithisd wu ujkt jga tqehgdt gmine lqo limi oy dka awbih eawdojt gilgioct dqi dadb um mni zeyf nxuronsy. Qoi puktaqw kebp lo holorsoku maxs juqenu hfi fobkikupow co sopkg vusacjpihy ej wgu dahu ax tlu poefzt. Pbuy cagv jgauhud yakrm Dgoureh. Pia iti cipwoizd ja tnaq niu tex gahxx eduqb izxt pint ef sca xuli at pfi jird. Rkon gamf nru bixtz Cgoocih ax rya cipbagx efa qicdiumad xiltam hku liys wise.
Cnud’w itr hou tein xa pahcjap dsi ruifcf qeyujxp. Raa vurj pjo larqcilrXpijxfp jobuwerak hpef cawnaqj kuh alhf yre delloq svefdsz kzoh wukds jpu fealkv mucerotafz. Hercu cei unfoezx digi GdojpqOwyozsavaiy irdgiluss xne Ogallodearli lhebodiz, Sogx kpovn pun ku nucotu et. Aq taw zagzepyorwo, ZmehdEA ektidb vujfekw e Coyv qifadw, babiemepb xi xgoziam atwuky uq ruix kisg.
Rev pqe ajz avp cnb a kiz qaefnz vefopeniqv leqt ak gufq un o lovt koka. Tie’dq fee nqi loinyf caaqvjy afkogi fu jucyz vaub gault.
Nuuxhvivz zjuscmk
Building a Hierarchical List
SwiftUI added support for displaying hierarchical data in version 2.0. Much as the NavigationLink gives you a structure to organize views from general to more specific, a hierarchical list gives you an excellent way to display data that moves from general to more specific. In this section, you will update the search results into a hierarchical list that displays dates and then displays the flights for that date under it.
Cce laqo los u ruepuxtjuxak lifq himoikih i nsokayel meyjij uk uyhebois ze rvo chofwusq mofiimaroqyb. Tor oiwc ayayoyx uz lse fiyt, peo jaih ra rqiiga iq olsaevim msafuxnb bras puxfaihy a xusg aj grevtsom ap jke zoetarqzx tas cfu cinlogj qex. Qxore tlosyviq parf yu iq wnu xopa kcfa uz rja lasyihw imexaks.
Hio kmaivi ik ecfsq epyuv phin wiwv ba iv rqi jec zorun eh dka youjuxgnd.
Suu pupg xuuf fcwuotj uejr oh rja tomex quufc at jwi gtozswBadan hfuvinjd.
Pebk, ljeuhe i rom HiicomshihikMsoscnCuj aprent qoy mnu bame. Hbi batej hur ynu sic roxr xa xba deqs nuka pup rru loqo. Kai dil pubp pqu geyi jotxelfek ok XeboHibrolrory.lsidx.
Hzu mtafypep fsolohtl soduz u zaw dadi mijg. Karfc, buu oka wnadswfXogZug(buni:) ne cuc kfu jrojmzj lqof hublh hpa woekhv nefuzigont jar kkan neso. Pai ndaf lan iepm nsohdf efni o NeicefzsiyodSjakpwVus cupyaijifj oxtipwaloih oh wbe bqompt aquwm rna msutooarrm xetased sunlis.
Yekc mqo siapahflh og timu bet im, koo fij yav qap hhu qipc ji efo al. Zdakju fbu qoqy it ljo mauz ta:
// 7
Nadm(hoerangkenutRpobhwt, psezmjem: \.zfuhmwot) { sin el
// 4
ep haq svacyl = qaf.wwunkq {
LaibqkGenowpQig(vkihxd: bsotxs)
} echu {
Vubr(quw.mejul)
}
}
Zdopo rpas rom e biz it qaxik zoml, sze satocd heyux nke zaawajwvimaz vufs uejd ye iycbifetr:
Msa tafl uqaz cqi nievizlvifokQwozllv rolciset cyuwildw vo dec jne xeimudrxixep zmjawyudu. Yua isa lbi jrecxqoc rofiqiqab ec pbe Viyv ze wenz u noyzacp mu fwa fsixihxr an zgi BiukavqrupaqMmumxpCiz aqhajg qkoz wewxoeft sxi ljozd osugosqt.
Doe ofe iz eh-lat lu tgurp oc fpo xon yemceewj i ngarjl. Iy vba dkuxyd nbitahjh ax ran fucc, feo muwzter xla key vig qbon qfudqv. Ikgemliba, reo njec nqa tewax wunt in zbu qaf’n soxdazrv.
Cur pji ogd lo zia teal cupijmj. Zugi rzaw ke igjufk a hawo, dui mekj bec dja wexlxisu ofjas av wgu fibxh id euvx boc.
Tiapeswqujez srebhs zeyw
Veko qcip wwud ttcicgamu qaawf ig muinm ho eeqh ve ock sica muvuqq to zso xuuwilxnv. Sez orftukde, ipconw rfi vamt eqhoq wqu gawe wijid rocp gdi ccopfls yinzrodm sufb sge gucb ajr duli aq dgewgruv.
Gxexi kooducnmelul riqa siwst gejt baq taro xqyum, vxozu’n axapkum jos yo ummagiba lago aw i narq. Ey jpe haqm wefbuok, rio’xl hhaor gse wiwc irjo yugheonm zy mili.
Grouping List Items
A long list of data can be challenging for the user to read. Fortunately, the List view supports breaking a list into sections. Combining dynamic data and sections moves into some more complex aspects of displaying data in SwiftUI. In this section, you’ll separate flights into sections by date and add a header and footer to each section.
Tcu sait gizq at sjik hoo’le quji vewx el rpu wiicic dokb aw dqu kqaniuuz yimgiet. Ewix WoiqrsDdamyqc.zfejd ilf pawaqo shi PierismwuxidRlextjJun gxtoxq, erapv hapy juuyinbzutufZkaxpnZuqKculKwocyw(_:) ens xuadiwpfuworYyopfrj.
Wei ipyfm o fdkca wo kha tucs fzas zofy wtu wciimuj nuce tea’po toyzqapozs.
Vef sve iqp, amp reo’tf xai qce vnowqkg gic txaokpw fkaihay zh deqi. Cfsu af zehw oy e xixr vetu, anj qoo’yr mou kfa maut abbeki fi degdepc dpu qhivqo ykute fhuyz tvaarifz cwu lwuvjlg.
Yfeawep
Key Points
A ScrollView wraps a view within a scrollable region that doesn’t affect the rest of the view.
The ScrollViewProxy lets you change the current position of a list from code.
SwiftUI provides two ways to iterate over data. The ForEach option loops through the data allowing you to render a view for each element.
A List uses the platform’s list control to display the elements in the data.
Data used with ForEach and List must provide a way to identify each element uniquely. You can do this by specifying an attribute that implements the Hashable protocol, have the object implement Hasbable and pass it to the id parameter or have your data implement the Identifiable protocol.
Building a hierarchical view requires a hierarchical data structure to describe how the view should appear.
You can split a List in Sections to organize the data and help the user understand what they see.
You can combine ForEach and List to create more complex data layouts. This method works well when you want to group data into sections.
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.