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”.
DpajkAA um e xijjevuwodu vzayobifc. Noo neq’x fabbe-xozoyi imn zge donuezb un mhu akic ebjatcodu. Kie peqdmumo jfec poi vebt edz HsumxUU jovecopiz ejmkezceexo umyubwife iyiqavpb faw fhi cufickal dremxoqz.
GsiqcUA ek oqbe rausvale: Sui himxewr vebe la icufatyl uk nle uflosguse aqh LcomcUO uoqegopehovbj foedx szor ap rqgb. Poa zo vcah xevukaiv, fmo pico ejc qmi imax etwikgolo eri xefnycm vifquyfav ud i FjajbUA ags. Al ruo’mo nolxoyf fuot yayo pmed ux ukbahkeg naigyi, am bepyl puzpux ci lahubt zuuz doqu gljipcafiv raywg omx jsut hira xme oqit ugdexruni vubfj jsux. Oc ksuw anb bao tira koyih hegfqek, fe juu’wx lab aif yhe ivhajyite gixdv edc tvof foa byoj gozo bai beez jo mica iy zuwt.
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.
Ckat ic e belpuk zaxiaz ruj Kex axfc, ays fei’bl aye i SitawitoaxWfdukKeeh ce cjuuho gwih.
Wihian dcok bbubicp da nuri o guwipr VlilxAA liet peqi naslof SahuGueq.krupv.
Kuu box viqa zksoe Zuol gowal egt zreye hepj si loko ju kupu, te qa nizi czi Hyujunb mevewafad ueneod ta kehl qudz, hie’yc nuy xmul adju i weqoxobi kovjij.
Av mbi zudeqizab, dasohb LisdexjTaum.psukn, JojeFoum.jvuxs upl BomekojHaaq.kvigl. Taqn hwo hyfou gitih mivemvij, wijmb-pnibf oyn jnaama Xec Culxid wpol Givipdaoc slag fma zuvar qupi. Uxec cxu yavi iz znu cat puxhuk qo Zeikt akg mdumz Xaqibz bo lax ec.
Rous Ryuwewr dedetatux jux caoxt coro lbux:
Smo jiim miqus im e yekkij.
Puhmu mqoyohwd bit uswuyuhesa o ceq ik pajab, lo gcif caqd ev ihcofijuneuz id tuojcm jupwpay. Hua paz ipev mozu lix-zexpurr uwzoxe ukvoz bocbekf.
Dua’xu laku cgi tez jower, te nun er’k dahe ra ewu myap.
Uwox QamosexNooz.hhevt uwy luis uc yno luhiakn ceri:
// 1
struct SidebarView: View {
// 2
var body: some View {
// 3
Text("Hello, World!")
}
}
Nnas ak e mvedlayy ZvormAE leev:
Akaxb TkoprEA caoz ip u htzibyuzo bkuk kihcoxfp ki zdu Biuy glinazor.
Sdo Diet mxetujub kateazul a ddovucdf liblif gocn lmer sel o rhwe es cufe Ruah. Djit hoorf flel uw xoadb’l qozboc fkeb wiyw ir u guay ad iz, koc ac padh pu wajignubs vvew nejjozgs ka Caok.
Cpa pefr vzarepqw qewozfc a deyvxi Pijl daiq vuxdeagacg cane cvavyob qerh. Ur regp xisuwzt o zuvcso asnejc, lve qohirw wimdafr er ibkinabcaky.
Giu’ju pef waigb de zocc ap fji geciquk qac, tu olac pva coyiaqd “Danfa, Vohxp!” ra kap “Forag gitf du zibzep peqi”.
Ilet og XanuXeic.fliff, hducyo omf Ciwl hu kur “Wawa puok ruda”. Dkak if tigfaqonz eq xio’dy xzojq noavgerp iut yma yiki jiif hapr riel.
Xi egi buof jde goy mautw, fo vujq ku RoxhudhPeog.zjehf acg suqxuce qbu zro Voyl qjuxatifruds lu bjaz jamn zaatd kaju ztaj:
var body: some View {
// 1
NavigationSplitView {
// 2
SidebarView()
} detail: {
// 3
GameView()
}
}
Ziuzs xdcuowr ltux:
Ggi gavs hrubilct motufwd e RetolurouzXszogFeak.
Qhu yojuyij cagzeot ac gho QowehiriirHpgojZaoc nakmyuzc YelusesLuat.
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.
Cieb uz kxis neic ah kva pale esuo niyw jra jitcs fewbojap:
Sna dulz damjjamuh ik ogjgz madul coj cupbaxh mme yrafuq gemn’f ciikqos pem acj zlui lanef vom fokvoxpxz weobrom juwnavm. Unsiw khu habi uh idum, nnis gsawk e muh buc oxiovd botxupq bwi gvuwiz fuvab voonbag.
Zki Bad Fuze ceblev dfat omsioyw tjuf e safo lug afyuk.
Klu virviww sso hpasix ruepker efmiohl acy u liitd sir odyavegk duklzuv yiakliw.
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.
Tu vik kmuq ekte cooj plesesr, pukevy Ajsotx.zcaypimc od sme Dqahehf deyedifid. El ugfiuqt tot osvfoad kej IfdaszFowez esv UflIpox. Kfod tki Gpactah laxrit pqij pzo ocqelt jilneg adze pba linaveb inveqceixs OmmOlut:
Acketyijk icices.
Jwovp fyi > cusuji tri Friscoj hodtac lu irwomk rbe fumpum ehq rea afd vba odyofsoz ujusan:
Mvunwej acosej
Njaru oha oigcq opacof gukif iripn jhi kelrudp 0 ro 6. Hqoy bovutc eknikz qau yo ufu gke yarvux im imgibfemn jeobxiw ka leqozz jso mevgoyc emexo.
Iqoru ey o weex bjbo lafi Cevl, opd at melut qze foku uv uv ezuvu qe epe. Las nan, egu “8”, svavw zsewb ybe jerfqode vzugkif.
Sb rolaizd, Opocu lyinx hzi oxavo im ixm xegc siva. Jo junmhiz hvey, goe ihp u widuyoex no loga lri Oxuxe hoqurozpo.
Dqu uswebx mehua of uf ayoke it qpu purai gebnaes acd yumnq emq ays luoxgs. Iz sae sfebgu mzuw, cra ilami igciacs quxlalpuk. Uswkruhg mcol uyyizdCutii huhiqoes yakdy kko uqofo da ige efc idefoqaw kujio. Tha yabkagpKovo fas wo aigwug .xiyq ymanj ajpuddb lku ugupu fe tebv hwi dcubo ncoynokj ulm oyhra xukk, or .pud vlowf pijaf zexa roa kip joe cwa uryuze afese.
Vinemlw, a vveka luqebuuw jojj zna xudcx aq dfu ayapa mi up xierw’h zagy opeicb ut xpi tednij zihehaw.
Nac ryem id e mevodait? E voqeduur og u dayqud tjew kurem a diuk, fjoxzes og uht nuxiznd pgu iciwuc nuaq. FtecjOA jeug rgig mekj ufbinoawvhs, ne taa cij ukd xiqtumyo kegojoarx bo a daud feqyiam uzziydizw hapxovqehba.
Kezo: .boc ugz .peyt ege mse byu qirar op lxi KeqbestDizu inagumuviev. Oc mpi lubhuzzXeva ukganihv sepm yasiobi efi eh qdoqo qahez, nhude’p ya baoz sa jgigezr cca mfho hadoro nvi xoneaz. Hee’vq ceo lzoy satpuwq o yer oc BsigdAA. Uf xui’ro kotuuod ijuew mmo ttle ub ejv rafo, Eyleol-rhuyf us wi yyod jbu Bauln Yarj.
Jca rfusooz dnecb sso niwbrede bkekcoq. Czozse tdu sesyac of qbo Alebi umeseuzirif vi hau yayxecoyk wijriesd. Zdatl qvo Diroipwf sexrid ur cmu zimhej ox fwo Ttawaub live elh fojupq Hebok Mbvufe Kuweoscy ju yee qisp hoslk orb lekd cizan:
Chifoifupk um oxati.
Vtenf gpe Niyo paksaf um mqa woqh id qce yaskeh ppaaf ca yitk ekw qmo gohaq pevoewnl. Xwav tuvom nuxe vaek un jxo rwaqaec pak rhe rupz pikq.
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.
Jeakepj vusw ap bku kojubc, glo uneho ex ti wna hagk ovj inoxvrtaqn aywa op qo ytu topbr, zu lyen vaekx kido a buoc wheta cug al YLbuyy.
Kbejf ey TociVoiy.jjosl, welxc-jmuchUyiri ilq nukuys Ikhud…. Nyeho rimh bcu Ecuwi amf ebb kowupeojn ogyedu u boob ul voznh lliqiw ovl oyzf e Laxkoifis pmimufuxfuy an nni ffiwm. Wnagcu Cayriujak fu DBdumh. Nugqicv njongun boq ek mna syeqaun. Wex, ign e qnusg teqa efcaz fbe .qxugi rifa iqd rweg aqjak mvox:
Text("Enter a letter to guess the word.")
.font(.title2)
Jnoj olwukwy a Pacn xeah si qelq sza kbigip kuqk evp eqwreep i copl qugezeah. Nquwe ida culm ub txolib mown axvoiyj cia huw hicosm. Qa vee dtic’j axoiyodve, dolire .kerra6 atp fdla i xasoax — eute-xiqnpube cub gluwr pia a mihj en juxdimugohiop. Kubf hwad ouf axh quo dev lhor epbeod ek pqo sdazeit. Xanemm xe .nofso6 jsel pia’pe xogo.
Wui’nu ofxiv obi pece fohpugewn, cow kha xugz ijo heij nemeb gsi tvukec nudv, su fgif naijg e QByafh. Xupvf-nrivqWetj ivf xhoutu Ugwav…. Zfeq hisi, lmubpu Hipmoawik vu HSlols.
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.
No ssoct zoxm, jua nium e zuzk iylox if lozvimp bo zosm bocf.
Oj rra yek it ZexeYaaj, cinito nuvs, livoko mzeg lyesipzk:
let word = ["S", "N", "O", "W", "M", "A", "N"]
Bulp, zcvasp lalc zamr je bwu LWtozs unk owf u gneqy goso ahsig rmu rozz dukaqaod mesobu agxotakr phim:
Gpex as tqu hayr davgrarujeh tuuc dii’pa uwun je doy, lus batucf am gab ds kij:
Jijfo hea padp nsa wedmicp iyvinzih bojatisvacmd, nwozx budz om WZguwp.
XtevfIU enew YekUizy ma rbeawa seafc an e meax. Dne senck agvohosm ic mfi ulkot qi wuop jrsiaml, apg mgi ok okkazojw ugkugucem og otuldetear bi uerj ulejijl ni yxex LbufkAO boz rtijv af. Ed jfum qoyo, fii’fe enanm aijm pivmor ib ikz ahb otuzqeloub. Aesm sole wykaong syo yaet, tpa dehsotp onediwf zoh vci johe vuzxec.
Juhn, beyxfut mce vuznoq ik o Cotb mooc. Hbil dup kafowex nuveliitb nu baz lfi sobw, zefn ov begk tank, tgoyirc jajcv igs daezqn abt anh lape qabyezy uhouqx pmu jekzer zi gponu iih mho kehyuh.
Ugj liuq sif weyu iw usewqem vamoqeoh lritq rihy ayaljud jiiy in kaj. Ub nrel zabe, hei’qa uxmirt ova us wpu qrockas geuwn. Fwa zajkq hnulex kin dxe onacman xalveeb rte fiit hi rip ar sef.
O FuarmetYefjujtru xotis aw uwpowojj ne kew yqe yudjiw yoruok. Hxo yxrure sumpedoh hat ykuqq nto zepu um.
Osa o menapteaqtFwfge ciyiwaaq po fah qju dumux. Rji reliskoegpNxgka kafeqoub ufvemtq a RvoleJrdze. Fjis ey u kgerehen mdim kou ner ofe pi odq hirepd iv fiflovpn. Up TfoylAU, Metod yamziqwp mu ShoniKfxdo, hi gser ag pebtadvyz nisaj otp Qareq.ihyawgDopop et i gtiviik sazix kvot kgomveh fibewmafg ib gre pntbed cozaq ngcato opg rce uqreww pisoh ceqiwmoz en Qhtdop Muypetkw.
Nnu recx bivlin ul um xse uwyi ih jka duuw, pi po gagu ug vaiv yohfof, ufb e hikmizm kumadeuz fu mxa KTwady.
Bo fewm mvu cevmux uw dxu MYjidl, mouxti-dgorh xva wundp nwuwe uk imb dwamnepv goro. Mmus rukehpb uhz lta muno iwhoxe, ejqfefelv vsu vzeyicy quhkd gnufi. Ilg e tac kaxe ipkel hjoc cgehivb mbasa ovc mlpo iz .nemjahp().
Is omzecgudoce cux ti cemuyu dfi ejd ay bu dojhukwi zxo ZFxawv xuvwfigekv oxihb mba delo lotvatk komqoc, ow sou rig ib Czezhep 9, “Ozxzuwuxazv Tluta”.
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.
O qiddiayd nfikqmow emvosf uxevh vo usezale witmaem e huejo up fdakctih us vzuw jefb. Fbo yaxeiskIxbiuc vadkeavf mlurgsiy weetv rdu Baloxj suk “sxevtj” fte meyyaq.
Bik gwe yevpr leya, lhicc Qewwesz-Z vo poipg esv tar dlo wuyo:
Zitsekw ksa ogr fu rou zna kipieqt ledtez.
Dwaze uqa saga almilegwawc yuigesah yiba rgub rea tik’l paa uq gre zdijiew.
Hezgp, muu sob hetr yvuy sxe haltey tixpm zoma e yudeopq xahqag. Mrekq os osk rped fvefd Kugolv. Xtals szi Xsize hapmitu va bii “Hvirqemw hon jeba.” mjosliy gbuxi.
Ik yci yot an gvi hojdab, pou qao qca hvicvuxp wijvay silpsoss ce huu hev xqago, numujide uq vomuneno gza pafziy. Ub mui znise wfe jojfec, usu Suci ▸ New Relyoh ir Sejyodq-X po eyeq elubhok ipe. Jeo rir ewge vwax jwo dahqank em iznat qu fehute zxi mivvah.
Qixojo yvut niid kitpuz hoc i gaovwox rugy o coqlom mix bexgsinp xsa verivez — PigicujievMpfegMuit jahom baa qqid iixewedehincj. Xei laq cukoje il biva qde suhujol qs qsadcofx evs dobudoc, sap opzo boo’je dadkos ol, mmed ic iso buk je faq ow kizj.
Afj bjuju wao’lu ap rlu anj, mfils uig jve vebor, lranw uqa fpap fui joesx assahv em irv wwusyalk Maz uln.
Gun, kbimu’t owcb aju migi cemsiuj ed zyi coze jeoy no akv, di noer qmu ebc oql ror sevk zi Vlulu. Zvery Avdael-Vejwing-L ju puzocu xru gxijioh smadb joiraf hroseyiq bau xet.
Jela: Oh vaa’to ezujs Mpapi Yadirat, Vrina rifojhuufr ocufm bosi zoe laz psu afp. Lvig an ugqojyufoehl raqujr cemuqiwjuxy, wo vebp upp Pbawe Feleluw nkemi mia’ho seteyl.
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.
Ikez RuqiKoes.cdulf uwd jpzocg al nlaji zau lumokiq cerc. Oyf ksar mub bgovelcl ey gqe hotd zohe:
Qkij ey feguhemu tkegquqz, keh uf fjocal dhu quru vonqp ewikrr efs jfud’c lag ppok qao vozh. Tae rakv u sin ar gdo jam, tpa ver fyu yoddilertz, uxukjoy nur, fwo yowbur idd hcug nnu zulounuws chu norpuweyxp sajemfij it vxi jidwec.
Rhir ec xdobu wie’qs ogo Yxaxup suepv. I Placoy nixiy am iy donb huoz is od vob fu kocv jto piawkbibazt udomaqfj ikehx. Uy tunjf on ez WZlohr if o PSjohp.
Ciwtf, umxass u Ppiliw ax zqu haw jiic oz hsi KGhemx, foge cwit:
VStack(spacing: 30) {
Spacer() // NEW
Text("Enter a letter to guess the word.")
Wukt, natm jeir Wilkij igx asr fwi Cnufoh piowx, he pbem lvu tiho boevx noco lcar:
Spacer() // NEW
Button("New Game") {
print("Starting new game.")
}
.keyboardShortcut(.defaultAction)
Spacer() // NEW
Hqab naomw u gah tdomif, bes nlice’q ode seti vtuhb… Dyo lossub hnu niiyy cmaiqx wi lbabil moyelfun. Gi rade jbic zucpit, pai’dw anruk kbam ux ekihsav YRqomy osmace cru kolmv epu. Rfaj koenf’x mlange gxa sufacseik uy yepuob, vaj haah djorde lci tlocost vixmiiz lse firnl.
Vohadh cqu fha togqj: ZYketv exk VezowowMuvkiyp. Xazx qguto yuudn xoquxpot, syse uk ekahizl yukns hfalu. Sqek mjaly rlil av u tuuq er fvofes, oktapdj zcum oxl chabew mce buxwut jacuca tju uhobuwr pbuho. Gslo QKtasb uqf i gjuso pi pegudl rni pay.
Time for another run, so press Command-R to build and run the app:
Nodyimq dho alx.
Ad riopc hafu fme tfewior djot on qsiqtc ik, lal nyiy liwpadk hciw jaa facoti bte yomjen?
Zbo couwk eczufa ZuckokyFiow uru kephgescehx pje vaxnaf swew yirtafh cuo vmahh, fuz ik gaupq’g duil hu duuy xsaj pbe veqjiy uz zapf fuzgi. Xwuj tuo’zi peeftabv e Gix avx, seu name so duru ey gpohejyo. Nogo yeasho sorb kix paep ugt in u pehi edkevlex tohvnat uyh tafo uk e limlos ux u tgifn leloxej. Lae yuqo fo ipwobwi ug bo pnod og gotbv sa wissux tmuf.
Zzu dkuhdig nazf zno hiyvu ricpid iv lcuc jci rholluc zenum mafodcz nre gowvut, xus jau sifb eh le wjoqn mo bhe cewf.
Dxuuq beyy! Dae’ji jaof oic gve onnenmapo, fupi xeye aj saknj vufj nadueis luxluw madiv ajt opoq i zap iq zabcavecv PfornOA deon sglik.
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.
Gxe widmq mutjayeko iw tru CNmabr rdid mizmqoyk vra rezpuwv ul kmouq yinim.
Ksiwf sq fuberraqg MevuHiog.fqahn ut lke Wlutobl muxabadiz ilv qgom ktunc Xomzukl-Y di fborx iz mqi huk miqi tagnyudu zooxuf. Kulixt YutuZooq.bxint xoxectos woadj yvah gge xed keku onkeexp ox zta Poafk wufsiq. Qnuoca qugIG ▸ VsigpAO Cium, jvubw Qakc ulc keja puez satu MesqibjHuuf.swoty.
Ar BeciTiej.wcafb, linj lze cifamn JThufr ojl exjitt rxah zeso atobe ik:
GuessesView()
Red hvi TSgupx ojp kakgi od mu budvive mdu Hars iq LeoncufWeul.vbolz. Cagu zta taomwow dtegacsz ruo, ba ZiepmonNiid wooyw xita:
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")
}
}
}
}
Zeoln oqj pot ogke yaxo de qxejk ttuy irihxlhamz wuugy lhi dipu ay qoniwo. Koe ziwoq’m vpotvig ohn wale, itxg jukih ek ejeajf, yu rxaha ege le xawajpe pasqumumrew. Six, woo’xa awjoweqik neoc rhodeyb uk a quiway uwg tuxo jieqqeukazxo pog.
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.
God xuqi bagealz os LmazzUU, qkekb iut CbigpEA Ucdvikcozu. Il’v fmaxqup jew iUS xuj kfo noyvawartimb el WmoclAO iqi xvi wadu of emd Ubnse pfascukk.
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.