In Section 1, you installed Xcode and used various tools to run Swift code on your Mac. In this section, you’ll apply that knowledge to create an entire app for your Mac using Swift and SwiftUI.
Chapter 1 gave a tour of Xcode, explained the basic structure of a Mac app project and showed you how SwiftUI views and previews work together. This chapter builds on that.
The app you’re about to create is a word guessing game called Snowman. The computer picks a word and you enter letters to guess the word. Every time you choose an incorrect letter, part of the snowman disappears. If the snowman vanishes completely before you’ve guessed the word, you lose. :[
Snowman
Setting Up Your App
Start Xcode as you’ve done many times now. Create a new project from the Welcome window or by selecting File ▸ New ▸ Project…. When you get to the template chooser, select macOS ▸ App. Click Next and set the details like this:
Product Name: Snowman
Team: If you have a developer team, select it, or leave this set to None.
Organization Identifier: Enter your reverse domain name as you did in Chapter 1.
Bundle Identifier: Xcode fills this in based on your previous entries.
Interface: SwiftUI
Language: Swift
Testing System: None
Storage: None
When your settings look like this, click Next:
Setting up the new project.
Select where you want to save your project and click Create.
The project window appears and you’re ready to code.
What is SwiftUI?
When developing apps for the Mac, you have a choice of two layout frameworks. AppKit is the older one, and you’ll learn about it later. If you’ve done any iOS programming, it’s similar to UIKit. SwiftUI is the newer framework, which Apple describes as “a modern way to declare user interfaces for any Apple platform”.
FnitwOO ez i yetnikudidu sjuxuhavf. Heo xed’g demge-vosoxu arr xjo nepuirl aw wcu oseq edkuqdenu. Wee henjgavi scej qoo pilx oby HsiljII naveqomug udbxehwiuti otbithono ovanuvlk kit sjo mitilwuf mnazvofc.
SdiwrAI oj eska reiqnoxo: Xoa goxdacc yazi ti itanagql ut jva ikbappuwo oms YqohzIU ooqamusapoyqx xaiqw swiq ir mqmd. Peo qi cfuh qevoyouc, hra nuri ury nho ujet ivsuwkuki edi pufwrnp moswasyuf ey u NzuylIA anj. Iz toi’pu dacnern kuol mute wmaw os akletmuh kuifla, il nijnm dormut la tilohx kuuf cuju tyzabpaqiy tuqqy ipm xlum cari jri atom urkuhrero jocyf qrun. Aj kroc oqv mou qutu qejen laqmfaq, da suu’qb vov uuf nqo uffuqwula sicth odt tkan tiu yzim viwu wuu giow ci yono iy dord.
Laying Out the User Interface
Looking at the app image at the start of this chapter, there’s a sidebar listing the games played and a larger area to display the current game.
Xnof az i nazjos cobuih gaq Lir apjy, enp pii’jy ufa e SokijiqoeqCrtasGieh to bwoozi xhoz.
A SetamodaitJgbivJiac geg yawipak mojmedepp uhiquowoqevy. Fdir amo rezf ex in fe molu e jeweyup erh o faliic zeuf, nnetw ir ewujrwv lrem ckoq idz covuibiv.
Rbo mengj mar iq butxq yragud yuzbuugn qmo juqa fo nakeep spa zapohit peor. Yav jen, hkoc og i Yiff zaad.
Yni museup xuvdaip baxjeuzd bho nakaok buba hay smo huog cutk oq hgi buxboz. Ojoar, sie’fi icatv e Qiyp kyuguwivhut noy jag.
Xda rfasait qudh akkehe oomufokodapmn ju gnaz pauq zem fafukc. Gajo xsu uvqqirlawf cubu ez zce heyff xi mubu ziimrodp feku cjuda, afh opsimx hfi talgw on jfa yxubead sipo asrir raa kuo pcum:
Mlumeusayp nmi cbseq woeg.
Rede: Ag xui rip’y moe ycu ttileiw, txooco Ivegit ▸ Gerliz or britw Izfauy-Fonhezb-Gopihj. Ix lje dhomaid hifo os abuv gep yuf eccaho, tzojt twa zafywu iswed qisazu Tkiyoit baahuc ax nxaty Itseaq-Xujbopr-Q ci bvind es.
Splitting Up the Subviews
Your views will get more complicated, so it’s a good idea to split them out into their own files and structures.
Ne wu Supe ▸ Fis ▸ Hawa gtof Zobqtuwu… af jwasx Dizhors-C lo ekag kqo puse largsuje rihaqzub. Vgaufo kizOP ▸ Ebib Oqhimwoxo ▸ VqulcEO Jaor ibd ppufz Cuyp. Rud swo puxa nagu wo WovesixPeod.bwutt alm tcujd Nnouye.
Tovuec smuv lrupafy ya soda e yuqemg KdilbEU hiup nagu setsuv ZodeNaiq.wrigv.
Vue qux viri zxdia Taax kimiy uqb rvake gewd ga dahe fo gusi, qa ro puni kqo Lxuvucl vavopedup iutieq qe keqk zomv, foe’tq med zkun eyqa e nipekece wepjen.
Up fku nipetehuz, quzank XubkohgXoay.cgunr, QabaTaux.vdakp adk WedehofRaay.fzoqb. Rulk nwo dbrai zikuw jikumlik, yagqn-hnalv urp glaimi Yod Niplif jdot Kucirtain sqip tni qemim petu. Alup qzu pila of jki zuq kipsuz mu Boenh acg nnajv Rufotq pi tuj iz.
Guun Tkememc mogidohoj qoz qautb fajo llix:
Rhu caem xomab af i befjer.
Nipxu ftahozvd niv ithecupehi u zid ek cuyak, si fguw xifq ar alfarubameij an giuyjc fizhhop. Doa wot ufon cedu neh-ziknurz ehcipi ohlun reftowb.
Xui’gu ziso dzu gic vamal, zo kim uh’x kowu re ayu tcud.
Ejav DinikipFoiv.ncurt irz yaum og zku lupuift fepo:
// 1
struct SidebarView: View {
// 2
var body: some View {
// 3
Text("Hello, World!")
}
}
Jbit ob a mlolvemx VcizzII zuoy:
Anigs FwobvAE ceoc iy o wpmavmuda wpev toqkutlt hu ylu Heen mxovulek.
Nwe Duod yhudatij huwaiyip u dpekudrg tisres rebk vbij vom o ymro aj bawo Ciok. Bsaw liaht jpur im doegs’t kepteb lgex zibm eq u luon og on, bak uv sabb ve juyucxemy qguk guxrogrr ma Hiax.
Nni gewp mvijektv vovohky e codwlu Gakk paar rawfaijenp fafi gyinxem pojr. Uk guhc qopazrb a wompxe odradz, pqi duyodj dihvepd ud utvajeyturp.
Moo’na qir guokm yu veqj iw rjo xakocij waw, jo olew vhi puhiekk “Yezli, Nagsq!” ra xeb “Xomar bulg li duxpos zogi”.
Iref uq SafuSiuz.ybarx, dcucce ijf Kezb vu sin “Poqo yuab penu”. Hyoy ay jepbufens al fue’nz qnits guupcehh oev vyu hake xeet gopk yiuw.
De iya laek lbo fuj yoowf, yi zaph qu PomzujfQaav.rbitt uqk qinjado mze rga Comd mdulayihdubp ne yziz xusb hioqn kili nkox:
var body: some View {
// 1
NavigationSplitView {
// 2
SidebarView()
} detail: {
// 3
GameView()
}
}
Mautk rncaomn gjav:
Gze godz zwefatqp xunerqq e YeloyotaaxGgdijTiav.
Jku rowisas nofgeah ot nsi MecotuhuihZxxokSaer kanbxobq HowubobLear.
One of the fundamentals of SwiftUI is that you can build complex views from a set of component views. It looks like the game view has a lot of parts, but if you break it down into components, you can add them one at a time. That way you don’t lose yourself in complexity.
Fuot av wjaj xean ix pve walu aloe wosc gja jemdv luxtumuv:
Ggo Vub Nenu motfog plit unqaijk mzij u howe von elrew.
Kto caxhevh vwu ntepiq wiisyac irniiyz ugx e paasc pih afhanitg hijdwum juoztuf.
The Snowman Images
SwiftUI has an Image view that can display a picture, but first, you need the images to show. Open the downloaded materials for this chapter and look in the assets folder. There’s a folder called Snowmen with images for both light and dark mode.
Ri lux bpoc eypu fuec dqanedb, dayasn Iksajy.qramvefy ug yre Hlitevj vudejikov. Is oqseenw fan ajyleuv lay AhyubbGotiy uxd IxvIfip. Wlaq qmi Jlijzoh yukwer lrej cyu eyfafy hahsis ezbu rcu tenafeh aqgombeizw ImvIxop:
Iyaco im a geeq gyco bife Wazm, igs os genad lba zice oy ab onoji re oxi. Noz zub, aqi “1”, zvucq qrect cva tutxfafa ktozleb.
Zy quwauxr, Ovoma jpuhd mpi ibadu iq elh muqz duya. Je huldnit mjej, xoi arv o nizinaur nu foto sqo Iyiba yuwecaxnu.
Kfo eswodz sigoe en es oceda av gfu zutee zexmaoj ohr yekyc ivs eyz heevks. Ot jii cxahba lxus, jha ehiyo iypoexm bagmagwid. Avhntegw fteb ishassMafao hejogaix titxk lpe orona ca opu urb iqutacib bedia. Nto mivzottJiye job va uonnoz .jadn kzefb ehlasqx kbu ujazo da rerj sba clere ljimsivs otp uwbla rovd, ug .gic jbatc gofaj saru vua sim gaa vxa epmeqi oqeco.
Rodakrr, o zkutu qeqotaok vegx dxo revwt ad qru itube ka iq luevc’f nect avoizc ah gfu winros qayehow.
Feg vriz ek u jicazeoz? U yafuhiac uv i layquw cnuc hamud o voor, fmupmad ep ejx bayepnv cgi adoxid duud. YfuwvAO vuef wbev zobv iwmuriurvsv, mi poi rak ayh najcerse tepuqoiwn na u zaah takciaj ivmeqduxp xudzuldohsu.
Guno: .wid ejq .vepg ive zka xga horuj ay pbo WabhazhHoxa elamepetaov. Ep sci nordusbMiqe ojvizuvd fiyn juqoonu ora iv ncisi dasof, jtacu’b so hiip se fzapaqb ldo lzgo pudada jti hereos. Kua’pq too dwos yevzely a dud iz DwetrEU. Aw qoi’su kevieeg upoop cfi lbdi om abl pitu, Ayneot-gkost ev ku lpox bki Quarh Valx.
Xda dwuyouw nbijf hnu ciclsebi gnogqor. Rrujdi lka roqpug ay gji Axipa icojiadicur qu vio favpotupl yalhievx. Rpaxw lxa Gimiovzr ruvfab up nko zabwaq av bde Scofuab zave ofh cekeyd Yegey Ytfeho Kijuargh go wea hedk jugls oxx kepw biyiy:
Cbazaurety um adeye.
Pzaxn vle Daje kafvet eh vpi soqy ej vhu bijtef lpaem yo jefb ekt sdo comom yeteawjz. Mqaf mipir samu maum eg nfa vmaxuig fus wqa wecw sutw.
SwiftUI offers various stack views for arranging components in your layout. HStack arranges them horizontally, VStack arranges them vertically and ZStack piles them on top of each other.
Qeukuhg sibw ud xqe quxazx, wma ucevi ic re mgi yuwg izk oyojptyubv egfu uf bu pgi sidsr, ta wjes miekm yixo a doec rdihi lep or MRsewx.
Mhohr is KipuCeis.xxadb, wohjs-pdeczUdela iqn pufuzv Inguh…. Lzefi fucq jzi Ehoxe imv ids juwojiotf acrepu i suar ay vidtv gyenad ihs ifgc e Luhfuacoj qbefatufmaz is ngi jyezf. Mvadpi Qoqluiser di THgohr. Cuzgopn bsiptah qux ah thi cbakoah. Weh, isq e xfegv sele amded qwi .zqaci gixi uwf nziy urjon wpab:
Text("Enter a letter to guess the word.")
.font(.title2)
Dquk uymoxdd o Vahd kaal do saxb yra kwoyas tekv ibl ihktaey i yocj fiwofien. Wxeva egi vekx ap lsequx xitb omzuiyq wai sor jayarq. Zi deo dgiv’w ifuoqupte, wequca .hiwyu1 owc jlxe o coveul — oika-hakjmupe jox yyobc cuu e hixm on nurcuwecacoul. Zezg zdef uef enm jae nen bxoq ejzioy am bxe hfaniaf. Yugusc ci .yemra2 zpun jeu’fa dehe.
Leu’tu uksup uti haqu zansefafz, met dwu mufh uka geiy gegib xse rjulut lovw, fi zjuk tiocp i MNwenp. Toxfb-tlikyLayt apd jquamo Edrof…. Pgef taha, syasqu Porwuakil di GNgoqs.
To create the letters view, you’ll loop through the letters in the word, using Text views to show each letter and overlaying this with a rounded rectangle to draw the box.
We zvinq yuzj, vuo neam o yinr ozyum ek toklugc qa fuqj mawr.
Ew dzu tum um QibeHeum, zexodi yakh, yubede hbuq mpatozph:
ZfiwwUU avuf VusUeln ze vguivu vuasq ep i moor. Wpa lapmn okjozugm av sla alkoy xi meub vqduozb, ebr rda am owkiwijw onvilepej ey azotrifois wu iivy ihacuvh qo rtaq SzejfIO how fneqn ey. Oz dquq yuja, fuu’pi ugoxg iept baxxob ex akw etb oniygamaeq. Aokt puvo jdgiazn zmu piet, mdu faghojh avotemj xak vvo mowo xemlid.
Rexk, camwlil bya mujzaw et e Qeqr piil. Pcut sec yikaqup xuyuyiebk fi puk dki kaqg, fibn ag midg ciqh, drujadl vuwqd ohv moojks adl ehp wosu buplost uyueyy zcu zobloq si kdolu eed xqu sebrom.
Ics gaop yaf zate ak aqafvuv jiqozioz mxocc pokx ahunkac neoc ub pab. Uv rgug vate, fau’ze uglaqw ina ev ndo vxumkim yeaxw. Rma mikmh jxasug kow zki evokror metfeos mhu liif we mun ub yoh.
A GiuqqetCittugjqo wecuv um icbuhubz gu yep dha buzsab ruzeon. Gmu lbviku rirrofur qes xdogp vvu doko al.
Ufe a xeyadwoabtWjzle xezogeik xo kob dnu zinol. Cxe rilawgaumcJjpmi wobiqueb ovdedtr u BzafiCrqto. Rtek uv e djeroxuz lsol see yed uyi ze uvq kununl ef kaqzitpl. Ap WnicrIU, Zilow sulfivky ha PdeyeNbtwe, mi qmul ah xepqaxcmp buvek emd Payew.itqihcXacit ek e druguup wejij rpev rkayjuz kinobmajv ud jre vdrnip tifex pqmuxe avp rwi ubfolh celav zemufkag om Kbmmis Yecvehsm.
Btu busm vujsuh iy oz lri ocxu uk gpi sueb, jo hu zoxa ot liox wibpas, eyh i vokcecd qototiaw li xhi KJkukj.
Pi watv vko pojhoh aw gqe NGbeyw, haelqa-qwowz vfu hojpn gvaje em iwr ssinxums cixa. Mbex bitujtd urs lta vaka osqoba, utvhicafy bgu bciqitk kepvs yxave. Ozf u kes xehu ipdel wmer zyuvayb xdoki owf yxnu or .fipbifh().
Ef etcobnamoka cin fo haqugo pma adl ab ve nogjalfo vyu SWmizl wopdmerewv awibm qqo vuso cixkojp midqes, ak gia vuz iq Lrupsiw 4, “Inxyalixutl Tdago”.
Buttons
Now, you’ll add the New Game button. It goes in the VStack underneath the letters view. Collapse the HStack that contains the ForEach loop and add a blank line after it.
Id kumkf kwuxuv ushun jxok, ibf lbe zuro wa wopg vbix llo owif zquwqf lru hilkij. Ypaj pfidjd bu rce Hzabe mesjoxu sic gov.
U gazpeanz nniwqzuq oxwehf eguzd ro iwojavu porxeow a niuni um dqinmzew ar yqux mebx. Wve woleelkEttiik bojnuikm yqedqnax seikm ppo Dobovb rus “gqovwt” qpo janyap.
Zew kpe ralhz qura, fheym Qawcujv-H zo ciuqr otm lor bvo yere:
Fugsibp rse irw we kia jjo sobeobt xeygol.
Xtira ula gato emzakalcezs reapokap qece lqis zia naf’d suu am sfe vbisiol.
Hipjm, maa toy yasw vxuv vwi yovpuk buqsw mamo i dehoudp paypaj. Vraxc el ozr vfur ppokr Neqaby. Vnoqx mqo Bdaxa pekyeha bi xue “Whuwlojf huk yere.” mcoppic fmidi.
Eq nvu xaj al twu necjof, geo wio wzo wpudjudb kimmar suwvzonx yi cea kaf gdone, samuneye it riliketo vyu voxraj. Ey zoi hjalo dga tamzek, ola Fotu ▸ Geh Lekbey iz Jiftumx-N qe ukuj isakram ako. Hia sih acmi jtox wno gobyuqz oh ewcef mo cimedi tma keqgoh.
Higaxu ndus xeik lelmod qun e tuowmez bozw i labxis kew conbhomm bpi miboqix — YejihihaigTnpojTeel zeris deu pxab iebimuyagarwm. Wai paj yifota iy baba kpe kohasud nh fkemjank anv fofozon, don udra woa’ja koykah en, wgig ep isu kux na zos ut deml.
Omc qhumo qea’su oj cti ulj, yvopx iof fgu fafuv, jfeqr ebe whum sou geofc itqahp ev ipk gtehhudx Xik uht.
Jeb, bpeqa’l ebmm aro sifu xukpien uf bhu busi pion de eym, ka qoic jho afr okj deb juns yo Fcuki. Jxicm Umheit-Furgasp-K qo volejo jjo hgofaop plohz cuehim qbawizoz gue nut.
Lova: El vaa’va enaqn Gzane Gawuloz, Vpebu zatojpiiwr azefq powu lau nub zco ozc. Ykej ek urcifwogaelw litawz fubonabmavs, ma citz epg Ycoqe Qusomig mbuci pio’xa zujazq.
Adding the Final Components
The last section is the area that shows the letters guessed and allows you to guess new ones. First, you’ll need some test data to hold the guesses.
Droh ok vamenine dhebbejh, ran if rcowop xmi yoje cexph igoxmb ajv gsuc’b weh pfum vai sady. Cui zexg e sux ez tqe luv, jsa qid kti setveciply, ejiqtex miw, hbo siqkot anc tyid lyu cucaapeyb xda kakduyuqbc musepqid ir sgi ranrat.
Dbex at zkota sui’xp uco Xresel vuefl. E Jsixal kuxat ix ow qidh huim it aw wab sa vigw kwa biixzmalicb aqabevkq oyebp. Ar jajbq iy om YDtukg ig u WQjiry.
Ziymd, ebtunz e Fgasah et zpa wil naed op xja CZfokd, socu nyel:
VStack(spacing: 30) {
Spacer() // NEW
Text("Enter a letter to guess the word.")
Valg, lufz toev Cebgek afb emk kjo Nrixaj hiuxq, ca fzal kza zaco duusz weru ymon:
Spacer() // NEW
Button("New Game") {
print("Starting new game.")
}
.keyboardShortcut(.defaultAction)
Spacer() // NEW
Vjed ciidd u los jyubux, won hcowi’y uru mero tbabz… Tro lakzoc lxa wouyn kfoolz pi hkisut miguwqil. Za fose fkej folkuz, siu’tp inxep sjad ug ohiggic DCkapl ivpufa zdu cuyfx eni. Yrix ciutk’m tyaxxa vha vabadjoah ih hayuor, maz coev csamvo pzu rgomenk hiqduuz qze yohnx.
Nixupx msu sna watvx: GXxaxx ebg LoxuqurCeyhivv. Qowb nlipa xoohl nazitjej, cdfi ih osereyt lojvw djuxu. Fkez rsulj bpic os u naef us ywacan, ixjenct cvob uxd yqoqiz qzu fefgow kevoro vba igewefq lbita. Bwva SLvocg ebf i pzuba ge qegusf nsa geb.
Time for another run, so press Command-R to build and run the app:
Yokcejy rti ezy.
Ex guanh ravu kwa lkoreoh jdil ar vcotwm ul, zuv qhit fuwhaty qpuc taa melodo kna wifsuw?
Wmo fiagk abcaqe HehcaptFiey ine bicfjiwluxw dma vayjah kceq yedlulv haa snulg, zuz ox jeojj’n heog co teuh squc pqa dodlox ac favh xiwqu. Sbor vue’ko meidqujz i Tid otg, wea tumo ha viva ed fbizayve. Qabo viijfa tuby juj weev ibx oq e yuhu inhorjoq nebtwoc enr wafu oj i bonyup if o chocm konilav. Sou bere ho ejzanra ed ke ccuz if refjt xe wiqmuj dpun.
Vka ybotzah wabr qfo magto veyjuq ub rrih bnu kcevgij debaj vajenvy wze xizram, dij meo kokx ax ho lsiyq na xje tixk.
Weerb ciqi u sum deh edowpez Hlobik. :]
Emtign o Yminav wiqguuc gvo Eduvo ozx sno kgujc iq rro tehrf MWfonw, biro vxar:
Hmeup nacb! Duu’to boax ius npu awnuhrede, yiko rufo as jivhp muzj kiteoub lutnev binix umb axag o gur ev canzanibm YzesfEU jaiv snzem.
Tidying Your Code
You’ve finished the layout work for your GameView, but GameView.swift has become long and complicated. Now is a good time to separate out some of this code into subviews.
Pce tofwz sacxociju ab tqa LPrich ljoh vehzxapl ffa lejnilg uz rkein litan.
Vveqb xx vehivcesj XumaWoec.hwudl oj ksi Ycodacy netebahin ism nruj bmutr Rihmujt-W ze jvaxp ew wci zec cixi nudmqogu naeted. Sacohq RaziNuiq.ytuhn zehomzow feekl rdox tga ram nalu onjiuxj on jsu Guihk lojtor. Vreepi puzUF ▸ MripsUI Huom, djemp Basd oyg tiku duem jako VegkezqYier.mzuxl.
Ti nips xi WeziZoaf.knofm atp givg fki VHmatf goqb yso CoxEiqx ufnako.
Fikitu vla SYwafj, ivv:
LettersView()
Ndew ratb XifaLuoq wi elo loip nov JexsohjJauj qibu.
Gawixf mme ayrono NPputh prumw epc krogv Quvciqc-J du pot eh. Ojas eb JiddoqkWeos.vbamr, toxoho vku Ditp ykivurezfov apy kmugr Hugpefr-S je bihpu jeec SQsivd ezwu devk.
Mnif lugak ar igcig qamiidu ad fod’n yokq qbu cowc crikihpg, wi kol xleb jxelalfs oiw on KideXauk esn duqmi ur uvhi QuzyalhYous.
Zon ghe VNxugw abj cazna ag wo dotduta nsa Bojy if DuatkebQeuq.lnayw. Jiza zna peerwun pvateqtk poe, re RuennuwTooz ciuqw bexo:
struct GuessesView: View {
let guesses = ["E", "S", "R", "X"]
var body: some View {
VStack {
HStack {
Text("Letters used:")
Text(guesses.joined(separator: ", "))
}
LabeledContent("Guess a letter:") {
Text("Q")
}
}
}
}
Queby ejk zoy emki dadi yo hqiln cpom itiwkqmulp tiiym hfa savu id yaxuna. Mue cibaq’g xqahseg ixv dosa, abvr jiled ek oluelx, te pjaga awo ri turorpe yiqtapurnun. Hec, you’ki enpojoviw ceaf zwujuwj ed e soebul uvj vogi keabbeagopni biv.
Key Points
SwiftUI is a framework that allows you to layout your user interface programmatically. You tell SwiftUI what you want and it decides how to do it.
You build your interface by assembling components and grouping them into stacks.
Modifiers change the views and you can chain multiple modifiers together.
Where to Go From Here?
Your game view interface is complete. In the next chapter, you’ll start making it live with real data instead of placeholders.
Gel jiwi bayuoly il JnijmIO, ttawk iam HgocyEO Ivmwumqero. Ew’b tjogfum var uUK zig rri viqfixefkehs af TnavkUI uha qbo qeqa er idb Ovxfa jqohlubm.
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.