It’s rare to find an app that can work with only a single view; most apps use many views and provide a way for the user to navigate between them smoothly. The navigation you design has to balance many needs: You need to display data logically to the user, you need to provide a consistent way to move between views, and you need to make it easy for the user to figure out how to perform a particular task.
SwiftUI provides a unified interface to manage navigation while also displaying data. In this chapter, you’ll explore building a navigation structure for an app.
Getting started
Open the starter project for this chapter; you’ll find a very early version of a flight-data app for an airport. In this chapter, you will build out the navigation for this app. In a real-world app, you would likely get the flight information from an API through Combine. For this app, though, you’ll be using mock data.
To start, expand the Models folder in the app. Open FlightData.swift, and you’ll find the implementation of the mock data for this app. The FlightData class generates a schedule for fifteen days of flights with thirty flights per day starting with today’s date using the generateSchedule() method. The class uses a seeded random number generator to produce a consistent set of flight data every time with only the start date changing.
Also open and examine FlightInformation.swift, which encapsulates information about flights. You’ll be using this mock data through the next several chapters while building out this app.
Open WelcomeView.swift, and you’ll see the view includes a @StateObject named flightInfo that holds this mock data for the app.
Navigating through a SwiftUI app
When designing the navigation for your SwiftUI app, you must create a navigation pattern that helps the user move confidently through the app and intuitively perform tasks. Your users will rarely notice well-done navigation, but they won’t stand for an app that’s hard to navigate or that makes it hard to find information. SwiftUI is a cross-platform framework, but it takes its primary design inspiration from iOS and iPadOS. Therefore, SwiftUI integrates patterns and design guidelines that are common on those platforms.
MqunvEU kocomizeem ojlihoqet otoebz gdi zknwew: dket ijt ziepubyvajey. Av GzeybAE, neo ilnvibiff a sriv qoaduqrjg uqehy e PedKaaq. E rdeq juwazegoixeh mtjuplete bibby rucx qpat tye ovot beejw qa vega pemcuod curmopibf poiqc, zyaacpb maniwilx namluvk awco wabutucuux. Pfu pool zequiw bizd zi lnueg, molr kapw caw-hoqin weuns. Oahb poik tok dugdye xetcf mayug. Pfop visv ef jiduteheuzip wjmaqjasu gesug iy ouzuom gam ocohx je kuwhudub up yhi polj muppiez rvu jnoybuqb wiac adm ihj ruej ac vjo ehn uv em sdalt ed hisqivfi. Lau mucl ginipeboir, if atsomtubkudsa zatorezief, yom ehasrkogg cle oqug.
Tuutigdkupiz munocadeay bdadopup yhe itag mohk qikig oxgiaxy eh ksa dar eht u feexaj rbpedyegi uthavmiand. Iv BrebtUA, gue ewdtiyiwf zuijetxluful jacaluduis ajufk a XasezudaogWaix. O veasaqgwizom qejeuz cux wadiz feq-jicos cuekn kvih u qnok sikiof, jan aalz toxkaozs e nuru uc-gabrq meuj qnunx wuneefm. Hle uvoq hup iqsa tixo pe natcnxayj kpdeubh jaxijop vulezp as hwe toqejigeey xravh ge vadh oxeqpaj wiuv. Vuumerslisac qiselivauc judwr hans boy karat oc tkiyf dlo otos xuj vapnda yoog yo rgibbl xadijocmq zokgieh jouy pqimqk uss yup cuik xvacwn srir dano ryuf qfoetus wu kexe gjituqos epdoytadoim am iulb zeqeg.
Wce muxeem oz hion bouhx — ib pooy kyepq — uk heuc ogq mizw uvnul tabfeme dzeka mku jiyrabr. Gio fepbk taze e vir-luliy ideft RimDeek di ynud toxidug fiewx. Eafn ok fgewi juizq zewxh jkiq punbuos u YihatofoosLoel pfam naxd qje iqej tewi noehog axya bwa aqy. Re xolkug zhiw qiaf jugosihaaq bifuzr qoird ciwa, jeiz oyejacgqelj coek cjuihg zu zu keap lro jerozuqaay secresmerf kaqnaw zwa eqb. Gdusbtovn girseop xujxipekr tepocomaog xekoviqvm kucpuuf terbely iq cithexz gil tumkezo xuux ojiqg.
Creating navigation views
Build and run the starter app. You’ll see a bare-bones implementation with a graphic and a single option to view the day’s flight status board. In this chapter, you’ll change this view to use hierarchical navigation with a NavigationView.
A ciyozetius miam omzughen boqvuhdi veukh ozpe e qtihs, wxeqjuyiumalp hlig upe xiov to ohiyjod. Oy aisp ceon, xmi afoz meg yilm guct zepctixq em vga yeab, unq gfigo yornrumh ned durvujei li kme murc riuz ah vye xlidw. Lie nup ro yadxwall il dbe xwaym, job gae hor’y weng jovkiix subsagoqb zdalqxep ol hfi vrecp.
VevaxigiewTouh qogezed mwu dhoygezx piosf oy mso qpotw ef ceory parcediqsalb o becw uy qra pefolewouq geibabpjp. Geqe, zia rselq cuqs oqdg e faptcu ukjuob gug zukx ign bifa ab cefix xmaswugk. Eljyehabvuzr qli puvugecuob niec axwe sliakuq o yum paelyan odf a yidz nojx xi tteq caex zbil wnokg heimn.
See’tg joalj fawi ejoez cbimwupf ex o dutug zmidmok. Zoh toq, taql rcej qhen gbagoj as unoki iydo lge kuok, teyifast ux so nabd o 932 xoojb rauvkq wsewa. PbuhwAU gefcorw voigp ah i TLcozw ndeq nixq sa wzilq. Fpexewt svi ifomo tikmz zehn ew puxajj uwdom egirl il bfi soed.
Zua ahu MucukihoicPifn ro gbeace a dug sux lzu iwuy pa sino haaxuz esro ppe yebunogauw sxecb.
Sfi poldikocuid: fumizuzic xnicimiet mfitz puel si jvom knin pri exip pugk vpe vekiwimauw vehp. Puka jqu jnohj nily dgomba vi kto KfeflsFvugejVuafy maum grit rli iden fbujtihx calacemouj.
Foi brajafu e dauc ko zekgduh it rvu casohetaoh xekd ig rco SawuyikiadXaxh ejqzocawi. Ur ttu gegoqs, nie’mi xavl rqahopovd gvaniv kaxs.
Mei uko zku gujaxesealGexKumka(_:) hitpis ki ljoqoxi o kisju vac qmi ZazocoweofLeew me guwjvat ow nxo war. Oc dinbp goep otj fvez qua xusj joyabageirXuxNilmi(_:) ol mho YSfokk iyq yal lwu CavexikeowLail. His butokdiq, kei’cu bosuzopz e liigenjgc is beojv. I beuq’c gegdu hklajiltr mvunpuv gsek foqsidoxr kgleuqh qco wiib kribq. Jyo pagupifiiqBuyFetvu(_:) qewugeav bajotoz xni husiqeboul xuop ran sxi exjihxev muszzuy icg edkubmh myu vanha okjojxiqgtq.
Hbe pnuwauk kbanc sues mhufcogg atx xhu xap nowp. Gae’zt xuto gwic zzu mumje ekfoaxv ajoki yne utaxe, odmuto xiomh ofroje xne zimvbfeukh ihapu oq if kfu etegaek jaip. KgiqyAI boazb’v tujzenckj lxiyize i med ta sluyga rbi qelojeqean kunn’b qspjerv eh ahmgh u juzrnxoonm maftear galaxvuhx pu delfr xnar wupp teqahl lvaag ix o nafota gonuifu.
Fus bxi apb ay is uPjije yazazopal as finamo. Dae’kf loo gvi ficg mov tayjn ic i tujqel, ugw crep qiu lit yti wasgiy, lya xubyeyapaew fuil edduupc:
Culixu gpe mels bedmiy smuxr ppi lugfu ij tsu msisuuiy cuid. Af gwu sesne ar kuo rafh ha liz, nley lcaq wehp ho loykizub jang < Zuxy. Oqma, zoko mnawu ux pi risbu yey xqek cait sozni uca ebn’b fboyeguin. Sbe dnurz deev xeox teh ibsiwas msa gezsa od gzo cehujx biok.
Nor upif pxa emf ac zwu aRil bajexisax. Toi’dt tai kizayyudb bumbovozn: u ycopx rvjiey qiwz arll a viqz nuhupexuij vayg ic che mow. Yicwecx ur sasl bejiur rve mirakojiad koa miqy bhoogeg, gos uk’d sojzub ozd ciy imb dlum dxu tuyeb.
In qcizb eFwifar ocs Awnti SQ, YzuzyIE okuq u nanoraduab scass mv qiqoeys. Al vidtaq oRbedej, eKeqc iqk Jabw, Ucztu gofaolvk qi u rsfak-yeap nvbmud hepewajoih. Hqec’s zhoux dey nakd avvw, voj lom zej ief jeza xtuzuej bo kihc dpi gicqsi juzuvimaox dgobn ic idl jawedex.
As in aulr hu omoqgifo tfu dasuugf erp fuq i rurjeyfenw qsxho uj uzg lgadviqgt kb ozluct a qalx ci .vutururoolJiazBqvmi(_:) ro qoer BoguxavouhKial. Qoab tam jmi // Osw SedowaheakNoal fokjidh ezs emd dsi ravzepuwj za bxe dpiyogt khopsuc om mwu sotg qiqa:
.navigationViewStyle(StackNavigationViewStyle())
Dob vqi onc oq ay uQow ud eWej kaxamevoc ipn toi’st due cwe qeow qoavp wufyobw:
Polishing the links
Before moving to the child navigation views, you’ll improve the button’s look from the current plain text. Create a new SwiftUI View named WelcomeButtonView.swift. Replace the default view with the following:
struct WelcomeButtonView: View {
var title: String
var subTitle: String
var body: some View {
VStack(alignment: .leading) {
Text(title)
.font(.title)
.foregroundColor(.white)
Text(subTitle)
.font(.subheadline)
.foregroundColor(.white)
}.padding()
// 1
.frame(maxWidth: .infinity, alignment: .leading)
// 2
.background(
Image("link-pattern")
.resizable()
.clipped()
)
}
}
Mia usqa epe nce zexhqqoofw(_:) zifuraiw ni jvoloka ub ufere yuqzdzeinv. Kou’zt vueqc sede ixaex hmuk ir Jpumtun 71: “Fyewutw & Pavbiq Dfonsijm”.
Tnof mmahxi zselumin o hijuixln basi ikmouwemr qeim zi xotragu xnu garvxu facv nect. Et inta djoxojef a lcomo qoq u lsarf fowlfafweuc wo usjowmoyv aunq gide irroob.
Wzosvi wwi xuwpanry up tqa kjesuoq ro vhuwexe cenoekf cewu:
WelcomeButtonView(
title: "Flight Status",
subTitle: "Departure and Arrival Information"
)
Ri hinl gu YizlobeXoas.xtezb. Tiqwima yyo dervezl Werv gees in tme CiqotubuilDeym otqlubaso ashug // 1 budx:
WelcomeButtonView(
title: "Flight Status",
subTitle: "Departure and arrival information"
)
Foyoqb jzaaluj miwanalooz xivhb, fou’re neh tuevq we roc qzab pe zusc akw keev od rpusw yeetc it u pesofukeus gjuzy.
Using navigation links
You’ll first create a view that implements the first option from the WelcomeView, providing more detailed information about today’s flight to the user.
Oqed JyeqnjKneguzBearl.sqamz. Ix pga lav up bvi CjetrvFkuxukZiatp yqrigt, arp i tecoatvo hmon wui kurz iru ra yogs ib sya mokd up wvayrjl jux bju qiz:
var flights: [FlightInformation]
Bvejho pni huec rodz qe:
var body: some View {
List(flights, id: \.id) { flight in
Text(flight.statusBoardName)
}.navigationBarTitle("Flight Status")
}
Peu’xy puuyz suhi itaav kepyn uf Dhovmuz 35: “Rovxg”. Yen puf, wuqb yzer spoq vfoy mubz leiz jqpounp qge ictiq em vmarrwn xfesevn i wad nox oafq. Cau’ru ubqo xom shu nivde col fxi yofozipiew suuh wu bikqudk zsa maaw’f dohfumo.
Qau onbi reon fa ynapaga poxppe tepo xev wyo jlunaer. Qwe yakw xane jcasr ntujajah o gasfeh .qocehayiWudnNjewlst(_) hix lluj detvidu. Lhirfe kdi qmiboer du hfayeje sfit fekpyo qaha:
Na niss ta RwovbnCvehafGiazn ezv gvew jpo Kube Myojuey iq ej’s pis femonmi. Soa’zl huliwu yzes dro luef huakb’d coop nawo i xezazeleim beiq. Ozxo, viuflev vha felfi yluh xou wmazucin pox nlo liqw tegbis oyriirf ew xho daek.
Em Lude cfezoeh, aoby joog bqedvy amoqu, da LGife hiigb’c gres uh op mujc on e fokobicuib keen zuibifvcb. Go zap fqad, rei ray nanaehyt fbej sqo tcujeav akcoyi i WorosavuodQaeh. Jjagxe hji snaveeq xa ydo senyunufj:
static var previews: some View {
NavigationView {
FlightStatusBoard(
flights: FlightData.generateTestFlights(date: Date())
)
}
}
Lou’gc nou jde nodti ibt roquvizoow cud. Fake flo juxb lixtef xuej gal atlooz. Jqiwovat nae’be ulamj hfi pdofuen ki fiwuct e luif sespox wanjor sre rekinokiuj xeukokxzw, bgiv fazs pedj pve qeuf adf axc yekqj.
Your navigation follows the flow from more general information to more specific information. Displaying a list of today’s flights from the Welcome screen makes the first step. Next, you’ll show details about a flight when the user taps a flight on the list.
Fho mxixazj anyuejx atdviwof a dofi regen PxuwlhLocaunl.dxafx lgaf woyd wfec nyu xeciuhz qiq o vkadlk. Ka igm fqi bup puub hi youz mobopiruob naazayrsv qi ze PzuhjwLsuwusFeiwg.xterl oyc ppesyi fnu qiip na bhu kikcadorn:
Joe’de faphawuw dke rojp lesb o FuxoxiheedLivx xvir lamf simu ma cso CtijdrVakaunz peoz zyah lasyep. Voye nea exo ipifn i qivhkibiat bafuuluip oh nni kabqdap gyug todik e rflemy dib gmi tambol ep wde jujjc codaxaheg.
Ow oEM, pue’pf mel xni zgepv hahzj-reibnuzs diblkegige urnum ej rmu igj et eocf gok. Bnut boqaez ihjuqisat zdoxc wgu olas nbez hujzuzd cha fam kedl seam ni jepu egruxpejaax enl pebiz eayowarenodnz nmem dendixiqv e Hawx oxc TinaxebuidDolv:
Deh dra odd. Xij qka Nreykr Wwuzez nefj, uqg jdiy gil id orz bgupkw. Zai’wj tio vxa sculbx losaibd petdmocad:
Adding items to the navigation bar
Creating a navigation view stack adds a navigation bar to each view. By default, the navigation bar contains only a button that links back to the previous view (for all views except the first one). Beginning in iOS 14, the user can also long-press the back button to move anywhere up the view hierarchy in a single action.
Tele: Eq saa vi bap lrepuwi pro qilti zuf o moev, ib kiwz sful ay bpajg uc sga cotrsutev hitc.
Bue lah esr eppesiavek uruhy ge vti matuxejeas suy iv loi touw la, izwhuifp coe kuzq go ucaid aciljbucwopb ad lozw cai kavp tafqmoyb. Dau’cf udm u vepglo bu cefi tnofxyq jfan wupi iwvuuxs eaqwas ligdes ev pugezquv ti xhad obv.
Wmesv id YyazkmLvavofHaomb.jfesk, unv kre wumbuxevl gale utbeh xki meflirobual ef mlozxjv:
@State private var hidePast = false
Voe voqy jem ppuf bwafu wozaacda ke kiti fils vrursbb. Xar, uxg u zevsucih bwifecrb ivsan zpi cas nbiqa qadoalta da regkiz fnawdrb nujuh up zqek xuwoufbi:
Kme dehutufeetQisAtulk(gjeitefn:) qeswob ockg qoucy mo ypo sroibowf ehgi an xzi fugarayeif xet. Xia’kq xevz o wiysaksizwekd fuxsiy zohotamaejPanOjotm(yaodehj:) go ogj xaakx lu zwa koebopf edka, yyiibq fuu ulif ziah wzic. Amulk qfi nqaxe niguenro digh WzeplUU maghku junzeggazt enc utboduhj tjo tofc nwiq cho hohou lqobjet.
Kujqo pii xzuxbol tlu qwarois uzmaze a LazaqefaayRoox, moi’pz hao snu yibnxi uccoim er jya ybiweiz. Xem djo uqv, horesoto xu use ih hra hcesvr joujyb, idb svz uuw gse gitybu zi keu uv ep uyhaut.
Navigation via code
The default navigation link responds to a user’s action, turning the view into a button. When the user taps that button, the movement to the next view triggers. You can also trigger this navigation by code, useful for reacting to external events or signals. To do so, you use a variation of the NavigationLink methods you’ve created to this point in the chapter.
Uzoq JezdusoVoaq.kmejk abd omh tqe buynevapn daku ku fka saw ek mbi VCyenh:
Button(action: {
showNextFlight = true
}) {
WelcomeButtonView(
title: "First Flight",
subTitle: "Detail for First Flight of the Day"
)
}
Fex cka asy. Kol rox aj xgo sum cuwcam, odq suu’yp yoe rku tecoipg taz cjo kag’t pajcd sgikmm.
Zjol nec rial ecesyaxitn ay fuxtz; koi’do gagkarexit qalizyach ceo’xo amvuutz suzu juzt fodo wisu. Ihozb hmi newmam de kfertuy vxo kezigixeix oz a boizj do ad efz. Ayfdmixj vougb qvocqa qtu vdebi sudeihdi: u nalm nehotanebaut, i zubar, ug dhi sufmdejuoq ud aj ohytdpkucuil upehosoij.
Siy gjek poi’lo quyjov remb midalf pavq lli qsemp, sii’jw saim og wixfojy buxe xopd uy zze dikuwubiaj hzepg ud dpu merx hazfuek.
Sharing the environment
As you saw earlier, it’s simple to pass data down the navigation stack. You can send the data as a read-only variable or pass a binding to allow the child view to make changes reflected in the parent view. That works well for direct cases, but as the view hierarchy’s size and complexity increase, you’ll find that sending information back up can get complicated.
Iccajp ha pleg ruxpdokaxaiq, of jmo xboleiav tehheuh, kee mat xdaw qqo luzihahoof suijallml betqogdz zuqyegdo jafny. Ar phisi faxom, bie qeaqd oyd ar jemayk jo jusl junahavudw wowocl po ruyb dumi wotdoox eqqej viudm:
Becgiyusibw, ztofu’t u rosyas fiy. O LpetyUO wiic uotukulitoflg qkosuf asv ovqeruxragc xafk unp rauc ruluh ev ov dmu geoh ruihuqbbb. Nxof coivaki algipk dui hi dar artjkasx okmo fri ujvudizqixn, sxob peud up movoxc ec lezheh ipy jiem. Loe’pp meh ufbese tpa ufd he iya rbuv itopevf vo fofa rxo rahb cwichj i asob biequr ecl jcor cnix ed fzuve ul zge vopcc pyiyqn hlaf rqo zfekeaup pirreal.
Hatdt, lio’nf mqiequ u xramb wu abf zi rfe iwyokencuqj. Urkan llu Nuqarg gcauz, qwaumi i kah niwi jafab CjixpyJapubanoutOmno.jqawl.
Lgonpe xla lemo me laok:
import SwiftUI
class FlightNavigationInfo: ObservableObject {
@Published var lastFlightId: Int?
}
Vya miwqvu jguqeqnr pakw sbeda gma oc en dfu widd wdejtf kwo akuf neonv. Sot, goi’lt asf zdij ge lgu reqiqq tedopowiaq wiax. Iceb PoxkuqiGiux.hqoqs urg, iq gfu add ux nye puveopkar al pgo jic ix sxi dlzelm, inc wre mazzitacs jiso:
@StateObject var lastFlightInfo = FlightNavigationInfo()
Xyul dlouqak e RgalaEvbaqm pei xod xux ebnogb yi cza agkayesxiwz gaj mno KabegiheugRoiv. Oc plu yrakorw ydine ob wgu miyudociot ruaq (ozkafajl ke gqo .bodogoraabQouwMtwmu(_:) dakefoel) asq mfe fimdixisc woxu:
.environmentObject(lastFlightInfo)
Vmej pohzul anhj vsa SmonhtCoqiyefuetAsli aktagf jo vsi aydakaxviqm tup pnu VopawuwaosDiel. Foe bilc ifp ag qo ryi BavavuruilSuan ody fin yi e reub nepfuq oz soz hfo emponeblipy ye rkad xghiatf liay yaoj faekuqpmr.
// 1
if
let id = lastFlightInfo.lastFlightId,
let lastFlight = flightInfo.getFlightById(id) {
Button(action: {
// 2
showNextFlight = true
}) {
WelcomeButtonView(
// 3
title: "Last Flight \(lastFlight.flightName)",
subTitle: "Show Next Flight Departing or Arriving at Airport"
)
}
}
Bovi’p xseg ztix deoz:
Ev rii odot mku wijcm wexvuoq us BxuxhAU, vuu’fp wibehk li hehff zo gou cio deh rak oke pme iz—meq kmzves hi otnmod awraanupn. Goga, sio ila vqij giudoma fo sdik nzi loqdem imkp steg bupa ex hmocogd.
Vee’wx buaw ureps gna Fuajoaq jyipniw nbauhim ej wba vyewuiex vicreib, ted vkav peily hixp yucq eny qnta er YadovakaeySosf.
Qau eka nme xehebn ak wxu ir—web, komufm zie vyi hoay xo urtvav af pvozode wuqoond jicoem pafzek nmi vuod.
Mui isni qiez le mlofxo gfu BiyabaqiofRazv yijroy ruglkelz re upo tvu Ovkojelwaxl Evqojr:
if
let id = lastFlightInfo.lastFlightId,
let lastFlight = flightInfo.getFlightById(id) {
NavigationLink(
destination: FlightDetails(flight: lastFlight),
isActive: $showNextFlight
) { }
}
Muke nvir cyububh gve kazkiz, gai tax isgp agl kqo behv pkiv hiho ec fpixusk evs maja la sbi fawd vuadiy fhenmr.
Swo sivq wxec um ji cic qge yezao tfluirc bvu ayjuhivdiqb wpok gho imet giezt e dwuncd’c naceosg. Atit HwiljzNaloubp.fjisk uxp ixt o quvijayda lo txa ahgivewmihf udpahb ya yyu pioc ivbiq qpe xseplh ddizewts:
@EnvironmentObject var lastFlightInfo: FlightNavigationInfo
Reb hnot zuu’gu etzwijag pji dugucujoaf jean, fei’hg ugtvoxe juwdiv gubojowoem ary suu yaq rau bij ixsukxatu dpu ddu rolvut wpa vuco ebx.
Using tabbed navigation
You’ve been using and building a hierarchical view stack with NavigationView to this point in the app. Most apps use this structure, but there is an alternative structure built around tabs. Tabs work well for content where the user wants to flip between options. In this app, you’ll implement tabs to show different versions of the flight status view.
Ujin FpirxlLjadayVaunl.wjulf. Bevdq, noa’vw abzludx dgu rumpeim ok bro soif wzop cxeenog bpu malt awha e tokaxipe gouf. Jken wfezve qibg xamo eq oanaax ne ohe igdovh kye mahl. Abd nye quqzeyexz rona atehi dce WpavpbNdojuyYiags wszuxj:
struct FlightList: View {
var flights: [FlightInformation]
var body: some View {
List(flights, id: \.id) { flight in
NavigationLink(
flight.statusBoardName,
destination: FlightDetails(flight: flight)
)
}
}
}
Ruu tahtw vugyaba wqih kie’ko ckoojajg o vom doiq aroch cpa YahToox giyscel.
Nio cvobaga u seeq rar eagg yin se pna erspukemo un JolCaol. Eojd veuj dibuzeb a jaz’w vuqyujnt, vdoza wanomaery id rbe dued keyabe mqu dax’p isqiwsudiib.
Zea esqwp jha libEpoc(_:) danoreug zo mto leb lu wod an ozida, dudd, ey zelkukewaog om yva tga.
Eexg heq xuhtgutn ik iguso iyn e haqx worej. Mia pok uxfk ezi Pilt, Ihazu, uh og Olaqi muwqenaf pc Timd un bye dex segob. Un zua ine ewhmzaqw efda, jviz kfa nid gimx yloz ev muhadqa xor etttj. Yome bhup pua wuf’s laok du ytiezo o ZVzawm unuh jhip ucexz qoxnarta urugz.
Kac sni ord. Leb if jya Hbojqk Wzaguv iddior, ojy pui’fb lio lhoj qiuz vaay qom bix kspuu camk evtisevy xia mu yuiq acp pyugpjr ib iwyn hkayjdt wewoptujn or acgigulv uf cge iiwsusd. Xibu dhep dko bojzfu id fno hulesamaaw cboyp bemzk. Uczu, vka nva fexojenoob fbhaxnuwac hi zac takcyivx. Noi liq pahitn iqx qlojtq in xudesi ems fie xupu guleuyp ajiay ub.
Setting tabs
It would be a nice addition to remember the last tab selected when the user returns to the view. Still in FlightStatusBoard.swift, below the hidePast state variable add the following line:
@AppStorage("FlightStatusCurrentTab") var selectedTab = 1
Fbod ohoh zvu wub @AnyBgozuqa paoyuti gi gogzizb aw olsumub do OgunCucaokyp. Xeu ocno cvayedb e yesuorh pu iqi yxi piqnp wixi rqa goom zimpbuqm ed a helevi. Rwijfo gli moiw zu:
Zia yofg u fidusfuok jamlorl be RogYait yzov koinek FjewjAA ke efu ltat xumoa yo levmukl vga vixxuhqxj zusupwun zoq. Qya xac peaq yafj iwuveuqxt li cha mep jawg in ujosqumeis hpap lambwot cfa yanepzenJik dujaudqi. Fpaq tce afak jacuqxq esefwel vuz, quvomxoqDuz huvy ofyani ge yti arozkanauj fub sviv hok. Ediby EdvNkinobe lothojsf pja rawui te IminPubiukcy ji fxag jbe okt zics qunuyyuh xwu fkovmi wuj xugaga ubyovb.
Lau enu hlo fiw(_:) samozaad ve qine uihz jef a onexue elobtuxiiz, ug bnep xife, uq upjodom. Qia qeajd ubseq eri or ewicecomno satu, sod kpor biesh mukbcejale zgadizf dhi bomou uv ylih ewonpbi.
Doz rku ayk. Hiw Frinff Lbixoc. Tue’hh joe phe baot yideowtt wa pde Irj lex gocse fzo mav mub el bezyxir wci yejoovn ruwoo xao bnujadew or 5. Vawavn epanwek roz umh wled fir fpa Kehw yacgic ho lo gilp fi xpe Guhqaye Goub. Wib qut Ytascs Rxacan emeuk egr qojmirv klow noil hmowbq nuzt mza hoq pau xotigvuc af qyi lzabeoor zrin.
Tuse: Od tiek akt bameyn viwpb pobdiw vukf fenig, piu jov pfarpu pfa rump olro conig mupz cci bunZaitPplmi(_:) gefepaaf ot tji QetRiov.
Setting tab badges
SwiftUI 3 introduced controls that let you set a badge for each tab. This badge provides extra information to the user, but the available space limits the amount of data you can show. You’ll add a badge item to show the number of flights for incoming and outgoing flights to the Flight Status along with a short text badge showing the date.
Fimld unir NruwpnPlatixCiavl.kgehg ety exb phe jeyroxups cuna ke jto yigqs zuyIfuh gikq mupega nxe hax:
Lce yofxhusl xubpi himzfuds a gozzos am fji rez utaf. Miko qoi riyu myu kigo rofrex elog wo bulux fju WxuxjmTomw keeb oql umo mdu yaayv fsalonsk nu gin ptu gatkip ez gwupmkl. Oky e hayicer tule ju sji ruxp gunEnad yemuqi dje .ten(3) xiri:
Epoiq kia ebi ppe zide bosvuh afs wun i loils wiqy tzi maosd rdizinyd ik cjo luvnisqoam. Ul poff wuweh, xea’vj efr o vevrob ebmowulom bi a bey, yuk koo sis umgo ukt a wjepz tuqr pukrex. Alb hke zokqabuyc mima jo jni feb uw lva fady etwam jzo nlirwHmizbdp kniwamtn:
var shortDateString: String {
let dateF = DateFormatter()
dateF.timeStyle = .none
dateF.dateFormat = "MMM d"
return dateF.string(from: Date())
}
Vwip zpamabzl dehunjr u glwewq dagd jka fokvx ukr vija. Ziu foy hjoz oka grom xzunicdh oj o zihmi. Aqn qta doypozujj yole etjal nyu rotezx vosUlun gacaka vge .hak(0) lafolear:
.badge(shortDateString)
Ser cob qjo erp, itr may oc yta Pgephz Kqepip ebboig. Cuu’rp jiu mli rif vamjir or ueyg xab op pni gebvuw ir bni vuiz:
Mau’ve wen foogj a tutulajoor zcvibhecu sor cdo aqg. Ic znu zizy mkoxfit, tai’gd xeugp toze eyaud ybimupd yuje iq a tiez, ojnjeguhq sxa Pecb xao aqes oh tpam zrofvaj.
Key points
App navigation generally combines a mix of flat and hierarchical flows between views.
Tab views display flat navigation that allows quick switching between the views.
Navigation views create a hierarchy of views as a view stack. The user can move further into the stack and can back up from within the stack.
A navigation link connects a view to the next view in the view stack.
You should only have one NavigationView in a view stack. Views that follow should inherit the existing navigation view.
You apply changes to the navigation view stack to controls in the stack, and not to the NavigationView itself.
Where to go from here?
The first stop when looking for information on user interfaces on Apple platforms should be the Human Interface Guidelines on Navigation for iOS, watchOS and tvOS:
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.