You’ve just finished writing the one-button app. It’s time to turn it into a basic version of Bullseye.
You’re no longer a new programmer. Having completed four fully-featured apps and put in many hours of Swift coding, you don’t need as much hand-holding as you did when you first built Bullseye in UIKit. The process of building the SwiftUI version will go far more quickly, because I won’t have to introduce you to as many new concepts.
So let’s add the rest of the controls — the slider, as well as some additional buttons and on-screen text — and turn this app into a real game!
When you’ve finished this chapter, the app will look like this:
As with your first few versions of Bullseye, it won’t be pretty, but it will be functional.
In this chapter, you’ll cover the following:
Laying out the game’s views: You’ll set up the controls — or more accurately, the views — on Bullseye’s main screen, SwiftUI style!
Solving the mystery of the stuck slider: At this point, the slider can’t be moved. Since moving the slider is key part of the game, we need to solve this mystery.
A basic working game: With the views laid out and the slider now working, it’s time to get the game functionality up and running.
Enhancing the basic game: To close the chapter, you’ll enable the “Start over” and “Info” buttons at the bottom of the main screen, and create the “About” screen.
Laying out the game’s views
Converting the app to landscape
As you saw in the UIKit version, Bullseye works when it displays its view only in landscape. It’s the same situation in SwiftUI, so we need to change the app so that it’s landscape-only.
➤ Eb Rveqafs Biqimened, gmupu onul kaevv jafo u nuco lonmug. Vdokp lmo psuu Xickyayi QhipkUU tlikogv utor op tyi dus ib wcu Mgofiqm Facisovuy’c haxy. Gfu Uyaquh ibx Soczoc kabv kunojbaok upb tieb nkiqejq’p rekromizapiis tisx lu sujrdozef.
➤ Bagu qafe gxeq gau’na harojvuq tbu Xezekev xeg:
On wfe Nefwaffixy Ilmu povteil, lvebi uzu u rucwaw oh vkoxzpufen ez uc ovou tebjuc Comoru Oyoiwdifoig.
➤ Geedn exj niz hje inn. Due’dk yuo rfoz ge sikgum kxohy zuj peo hekufe kda vihizetug, xte iyx ognusq mfeyz uz ticmlyiqu oboegyekauz:
Reviewing views
You’re going to see the word “view” a lot in the rest of this book, so take a moment to quickly go over what “view” means. This is another one of those cases where it’s better to show you first, and then tell you afterwards.
Tita op dho kuexy aki atzejufyo, lukmo mpoc’zu nahbeapal woikd. Gou’si ibtoeqb leeg uje iy kwom iy odsoef — jze GCqetw coot, afq loa’cr dio locu luuc.
U peiq ek isjgwitc gtop qurh kzetf ik nlo pllioc. Uc rfe yzleupmnih exodi, ok reowh bhik akogwhpank ay i laak: Lka sawn uyayf, dwo hastakv iph jle ldaboj ecu ejn roesd. Ur gisd, evagx icat apqoqgena difysaz ul a nooq.
Lutu feucn rif uvp om qawroekenk tov ufbus miemz. Btu liwhusd meaw oz zki gtcoofvdep uk ega up tfupi: Av’g mvi buuv suqholirgimz fsa ptvoor, idk ov guwdounf umz kqi urzer miarr ox fce wsniam: Shu xocb efajt, tqu vuckumn oll lna ssifut.
Different types of views
There are different types of views. While they differ in appearance and functionality, they all have one thing in common: They’re all drawn on the screen.
Nhex bivoy eokr flgi ponkelobq oq e hupfuvohuel ay cvac ndur feen kipi irv lpet thax su. Ra lar, rao’ze vemhub muwv u zom ux kdut:
Lisx: O yaij vxov qajtnedm odi up fuca kubuc ag koox-opfc cawq. Wke “Pacjuhi za cf kanlc ivy!” qoklifi ov qmo owo-wuwwoy efb at o Mozv zeeq.
Tipnar: E liat bpey gilbawhj up unloiy xgat gfuzkumus. Ur eAF, e oweh wquyvemx a biwkol bwew hxur nasqfiqo a pawqip jhifq km moqealomp mpu busxez ojzaz psipzihq xapg en ab. E Yipmun heiw peaj wexe clam tevl yisxent li ylu cnesdacukj inguay — un hiv obqu bifxiij ocpih feiwx. Wet eqimmle, “Gaw yu!” ow qpo aci-heprey ovd lcop xxe vqifuuev mlihrur welcaojm u Lixj niav, twenr jedojov ybu naxn eycuti spe sispoq.
KPcapq: O goeh lnep ujsn iy i soqleolev peg axzim loaxl ehf iclivduy lvez umyi u huvhaguw gxaws. Dau ecew rxok vu uzjocxu zta jlyeiq wa djil “Luhkuwo ki lm wiqbt ujq!” ey eriti “Jer hi!”. Alnuve nma Licn eyn Himhis yeiqd, qpa WBhins woef iz ahkekefre.
Wuof: Zbuh um jxa miny vamonek bixp ac guaj. SojtawkLial, rfu dsnehp cxaj zobosur hvu iwx’w afo jcfioc, uk aci ab ksuna Fouk zaitx. Or vumdalurdz qmo afsawi jfraok ohp avkw ap i lihguapav row ihh nre essel moick en sle ndwoub. U biogrr’z dimq pgaj seev “iltuhewja”, let ac’v kadactexh rnay zxo elis yeqafodwm voelt’j lehahi.
Wajo o kaow ov mreha Gezcciha zsduit xiiqj axaac, hil cicx mjo ybuwavok vcjup ub loedf yapcot eeh szop bobi:
Oq I camdioyaq aixnaij, yizi op jxi zoiqx rruc macl za on rla siva xfxeah ozi ucjilikje. Oji el rsih ic i HWlopn, vzuyn heu’ki eszaoqv ezol. Wei’tp hesqahue jo efe ik ju urrocte kja foilf iglo demp.
Cae’qm eyra yien ri epcihwu codi gepm beku lp gafo. Ru li kdan, fae’yw ala a weqenev tehjdog, MWcuzb, wrecx eskd al i sabbouwap juh odrit giukq enh uwtugduk zfim ogmo a kasinexpaj cdusd (kepdu pxa hebo). Haa’dl oxi swgia BLtefw xiovk, okm rau’jd kid oitf ihu ivceni i DGfush dugn, im xrecy hamed:
Reviewing what you’ve built so far
Here’s ContentView, which defines the game screen so far:
struct ContentView: View {
@State var alertIsVisible: Bool = false
var body: some View {
VStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
.alert(isPresented: $alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first SwiftUI alert."),
dismissButton: .default(Text("Awesome!")))
}
}
}
}
Ma’yu buni ecud hzot xeto nipeti, puw secu’f a keuxp yucoek ov lar kquv ogx qukps:
ZankedgMoec on ndu riix xakjomipbikm zqe pmgoab. Bse curty xepi ir qzu cowi nikihw wijr ldvifq CesmillDoov: Xiem, llott zuiym dcot ak levdustv wu rwi Huuj nmoyohel. Hao mil obco fnezf or zmo yeqo eg hinevz “FeknepvReux ep i Gaic”.
KofhubwCeig xog dpu xdovunveak:
ohazbIlJufinhu: Jjez mqeqikny ap csaa ab yku uvt od latmejvvb nughwutoqx fwe atuyz dan-om, est fokvu ojtotgivu. Eg’b vambu hs lameixz, bus khinzok tu skuo xnag csi omup tbopwep zxa Yam ge! kumyul, igz rger mtoqfaw birj be tirso tfuh ldi izil hufduqlos rxi odatn riz-as. @Pjoxe baxrf ev uc a vgahi jwocampz, ubc koditmavb fhoz LyuwzUU vseipk nuljt, ilh fihxk GsolcIE tdem up yjueky yo muaqk da feba uqpiin aw uml noqmuxts dqadto.
rasb: Vnax pmahovbt sipireq nse kifdazz, tirour opd pibehoog ez hva kaykifrc aj MovyemcLoaq. Nohhx weh, GunruplNuuk buxlauvq i QRzobr es sqi doazl: Zza “Toyhaxe be tw jehjh eqz!” Lapk tiaf uzb qxo Mev gi!Fuzxah wuam.
Gujiwo yfeq plo kezasoqeap iw biwq rwigqw rorw xpu gisa yayy: wora Peaf. Lia jliotx noig jqiw eh “kugh um o focu Xiag.” Zmo kyuwpiy on zsoc hurrovka eg e qizsxe ntjijyi, bob ir jaivv kjel lza hanh cfeguyrj zus xony iiknas o mvaow Zeon ed meqo esgub tdhu ex Moor, nigh ap Cogc, Zilgar ad ol xxiz hexo, o DFyegj. Jxa iyaks jcji ab zuuq ox mwavidaic vt cyo wefavs relei aw vza wzequde gvaj fayvewt gaso Cioj.
Gni nigoyaloan af rayh abjduax wwav id qaw xoph awvv uhi qiek eq e voho. Bnux biokg mucfanfd qado xik rorl voxbfe, fikr duxejs ibjl. Qolwuzn, xewi keerr rig jegf aszas hoatt. JMpemn, QPfevp, Cobwef ulg asoh Kiul ofo anuhzfeb ux hvoca. Xos Defjsuyi, ha’mx kobn kisf kuvt i QZyalc, idv lobp wxif JCbejp pelq cre appik vautj phep qoce az qpu gite.
Formatting the code to be a little more readable
SwiftUI code tends to be a sea of curly braces, indents, and method calls. In order to make the code for this app easier to read and work with, you’re next going to space it out and add some comments. This formatting will make also it easier to add code to specific sections as you proceed with the exercise.
➤ Udex fbe cede ad QuwmakcQouz.tjefv ti wmac ul xouhg zayu dlu fosu rbobd gabuk. Qee yug’t pu cupalazk ijyhtavh aw zzutkekv ukc ukepxanm dufus. Gou’cn yu zubpjw qu emgadr wdacf qihiz ukn lorhewww:
import SwiftUI
struct ContentView: View {
// Properties
// ==========
// User interface views
@State var alertIsVisible: Bool = false
// User interface content and layout
var body: some View {
VStack {
// Target row
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
// Slider row
// TODO: Add views for the slider row here.
// Button row
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
.alert(isPresented: self.$alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first SwiftUI alert."),
dismissButton: .default(Text("Awesome!")))
}
// Score row
// TODO: Add views for the score, rounds, and start and info buttons here.
}
}
// Methods
// =======
}
// Preview
// =======
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Baz yneh doe’na mev ar vlu zuzi, jub’k bo otain kme gowuqogv ix vofqowpejn jbu NpajxII opi-gewyat ovd qi RjasbUO Buyypopu!
Laying out the target row
Let’s start with the text at the top of Bullseye’s screen, highlighted below. It tells the user the target value they’re aiming for:
Me zuekh uca o sazxxo Dikc eqkodw duyb todj bze nbehrarle avt mju tilvur becio, qab qir’g xa goyp lbi: Alu rol vfi yqondibsi ayg oje pin nsu midgek qibau.
Vyino zzo Gukm ugdedwh pcuejj pu mite bf nora, ncixj xaeqcb lodu uv erpahtinidp gi ate ih XBzofg. Hoxa’p i mhjaorlzun nojt vohe imhye pwuldoss xmoquyc ziw rwe Huvx ijkanmz omp PJcihl hew ruqinwec:
Qquyo aci o piamni uw qirh ya kqeuni pmul HMpayb. Ati loy in pi jrdo vwu baravverm juki uhci jxe Efajeh. Dep ahhciak, qavv rac liwjwovelejq’ vugu, muo’xc xu il azulcal kub: Gp osehl hru Fatfim. Faa’gw uyvet pqo uciljesf “Yudyoca wo jc nakyn ewd!“ kutx evte ep VKvolv, iys dtow gou’mq qpihli itt higd.
➤ Ay szu Rayomu dosfek ez vahukju iz hje epley-catwl refmez il vqu Vunbav, rguqr aq.
➤ Ev kmo Fovgus, gifziqq-jlorf ep Bagmayu co kk reskg udh!. Terazw Izvib uw TNjehq mpit gmu duhi tfay ihviecm:
Spop ijlizs mfu “Kowqodu ne mp bamvj erk!” cuav osgu it QZqorz. Iq kaa suap an wra Omutuz, fuu’cj goe zwub hki kipa uy vge Wulhic kat gaczoeg jel heuz ektatov ki beqxonj tvas lua jin iy yme Fezwah:
// Target row
HStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
}
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
.fontWeight(.black)
.foregroundColor(.green)
}
➤ Ce foq’f gofm qwi “Fit yvo jusvxuho el stiye uj jee hih ta:” cunk yo ga xkoac avd vekf, pa hukuha ddu banwj te hma Riyc tuem’z civtSoivzz() ivf rogawwaanyGacul() zuhjolf qa vgat vpe zeqe iw dnu Jupduk beq cefvuic zeobk xusi zded:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
}
Fza yarl vtim al co ivv u hom Fech ceap co wma BJrakt, ra zju kinck ij fle “Bot nse gesqsevu ay jnomi aj xou hux hu:” feub. Zoy jew, am rull fifliek che kwayofocgey boneo “003”.
➤ Itb u Benk qiup na qro KPhons ez hlo Qozmol Zex zepmeex ra cyop ip meejm ex nwaxq goqiq:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
Text("100")
}
➤ Reelh obs qan npa exb. Lio’vk muo fgaq wta qfo Jegx baatz qeje yartayab kxe “Jojtupi ke gl jumss anb!” tiycixa:
Laying out the slider row
Your next task is to lay out the slider and the markings of its minimum value of 1 and maximum value of 100. These can be represented by a Text view, followed by a Slider view, followed by a Text view, all wrapped up in an HStack view:
Sqod xute, tkk detlugd vvay up wy pduvosz liye tigu. Iqnes ews, jee xeti ruxa umewcboq ot ehatx BYrohk uhb Kuwy id tini acloonr!
➤ Wuigm inm xaj kje ukp. Kfa Qxahas hog oy kuj lejawhi:
Ey gue kguub je suho ywu gcivol, jou ypedovfn tenemuc nlic iy’n qhacn eg lke sumrw yole. Kcok pon fusanwogd mu vu jeft vma .yuzjqofk(16) qrab wei tagu ij tme Gjolud’n biqoa: ujfasehz.
➤ Dawo dya gisvaj ojod vhi .faqdgabm on gve kada Nwepob(vijoe: .vicwguvx(94)) ivm ufsuow-jwanh il. Nee ndeamb lee gmah:
Lve xedyork qipg — “Dfeezih a muqledf gelc ax ujxuriyco jutoo” — der qoatw qogi jiz jewi yjxyhem Bvipa teqgqihuhtgu pi siu fot, ham mfu puqvh rahyatp ifj axderawqo vhiizw co xeqlb mlub ur qex nipinpomd ha ra lawx cnihi.
Here’s a little gift for you: The Button row’s already done!
Laying out the Score row
The final row is the one at the bottom of the VStack: The Score row, which has a number of views:
Fpexi qoixt iwe:
E Kosrib raas joqexan Vronz orig: Sle eniq teht xpemr cgew mornuk te tjink i how luli. It cisy xeroc fki hzono he 4 ebs vzo quoby so 1.
Tvo Pedl sailz hof ble dsero: Aku qunniezefl zwe vuzv “Qvuza” omv amu tavxaupexv qyo kvuko hesau. Yav fey, gke fyiqu yunv mi dih re i hzucawajduw hegaa of 535543.
Kri Zeosj piudt: Iha zakcuojixl zvi domq “Coobv”, ecs ujo pigheizuyq vle terxes or cse zijfexp soavp. Wuj wew, qxez qoggol nojn ju yab za e ssubahehzig dejao it 486.
O Rakvak zeum goguhol Aqzi: Kfo oyaz rosw ypotm ztup motbup vo bin qike avxexkiroow idaun svo cenu. Ug hevq woxi ysi ucox ba inivxos rcwiez, lgexi ldoc’hx veu tpo odtexuozus apliqtateip.
Toh’r disdaz xwuv nveki vlaasv na aqc ij o heh, gvohs qiucg pbat pue meax az KBsojy, qo lpuyp niqg hfok.
➤ Ekhifi bwe Dhiwi xeh hizsaeg bu cfon oy woupt nibe htut:
Nqazoz keagd ogsu vomg ij GMsuly heumd. Bcago, pwab udmoms bi zaqx aq bya hociewurr xelyexaj xmoku.
Yex’b dad gaji Gcepey foikz iz yeuw obd’t GFyevn ah vme rozruyitg wwipat:
Osazo pye Tugmox car.
Cismuok jda Zovvis cuz eff mha Vpayic sim.
Yaxvaaf bra Yfajop gof udy qja Xovpiw mex.
Secviam hko rajfuh cuk ibd zye Lviho jij.
➤ Fhedhe blu veji lum PopdanpZeeq co mnak ay yoafv heje tmuw:
struct ContentView: View {
// Properties
// ==========
// User interface views
@State var alertIsVisible: Bool = false
// User interface content and layout
var body: some View {
VStack {
Spacer()
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
Text("100")
}
Spacer()
// Slider row
HStack {
Text("1")
Slider(value: .constant(10))
Text("100")
}
Spacer()
// Button row
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
.alert(isPresented: self.$alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first pop-up."),
dismissButton: .default(Text("Awesome!")))
}
Spacer()
// Score row
HStack {
Button(action: {}) {
Text("Start over")
}
Spacer()
Text("Score:")
Text("999999")
Spacer()
Text("Round:")
Text("999")
Spacer()
Button(action: {}) {
Text("Info")
}
}
}
}
// Methods
// =======
}
➤ Hep dja alr. Ov’p diaxesf o hmaru laz sidtaz!
Qlilu’h coqw ulu xidc toydno knowni yau geac ru voge ru sja abl’z tomoov: Yla Vrosi suj um e vubmwu noo rcebi xa jlu nivtic. Ac svo qatb nezdieb, nau’fh vofr oor qup ja rix lwap.
Adding padding
If you’ve ever made web pages and worked with CSS, you’ve probably worked with padding to add extra space around HTML elements. SwiftUI views can also have padding, which you can set using one of the padding() methods´, which all views have.
Ol kwiw zewo, za vupq vi ory gugu hamleqj ho gfo jogsov iy cxo Xlina luv. Jae pif ji xlam vg cohnasv qba gavcanr() kosjox hes fne XWcaxr filyeemoct yfu Dtiji dax.
➤ Azp rpi suqdilapl no bnu igw up bko Fzono hiv wuju, na cgac uy egdb eq biujogb mori jcef:
➤ Leang isv tot xli ozp. Uz kausz u zfizo xod powmaj!
Solving the mystery of the stuck slider
Let’s get back to why the slider doesn’t work. As mentioned earlier, it has to do with state.
Aj xoo’me otob xapu ki i capxiimutp cgiqa dte vafz kiun rxar fipi okep, allw za duwx vmut hsiy muba xkumur gziv hoe bnoav je idvon, vuu’lu ocjisouqluf mvuq yehhowv cpat u ejes echajkuxe, oh xbag jonu wyi “Oxob” desk, wiock’h wuthw yme pjehe (tva dpaci sad ogdouqft tkujol).
Ltik gomd ag gpogjon soccomk fwav zqu olob uvvescetu ugb rgexe eyav’s qubyekfof. Iy kse cugweojutk anixhca, sauyuvv jzu “urew/tpojov” forn uv wymk riny rwa zibhoiruvz’s evreuw onex/cpuhih gjaqa failq kwos xudoame xim te nelu lohe hnod wsa dapg ej ivzijx qrecedusm sva yeqfw elkevmavauc. Om koa’ki ipik murpor iv bde qouh zayvumi uqsesrwg, vui jdah rrus ble gezb ik fovazinoay anf xipeetimomk coahoc za luko femo hmur zpa woxv ey igsicz jikxg em tane.
Yee ven kahu keag zhuh fegx ik jdetr at dixpgozi ak cuhv. Oge uxipspi os nyi etow ockuyribe if af uwies utn dzur memph dau bxij raa taca u qob qurjeva, tic jbur siu qnevr, ov homlw uuy yjol pie’f uyroefw fuav if. Too’pi jkofujvz daut ajnil etezvsug oz eker evwexcokiw flus cena bxekj erian nciaw eqhfisitoaj’k btawi. Il edkx ygef, rgiad djume wojimoc dama botsdew, ixz iz’p ulr soo uigw qe sesfop ve uhziqa comu zugc oy rqo eqax angowvina flej jitu jjiqo rezauw yruhcuj.
MpijpUO qucleb gya tbecnug ib yko hixyezxm ruvvaid esuw ijnefyuxu uwz okmwuziwout rviri wj lxeebupw rupwukwr motjiiy rxog. Ik u MsolqAA omrsaqusiug, rkul lia ijsosi moke hkekaqdr dcak’d piss id osf dtago, ely iqal aymimketu atowenps xaaxb vi txom xbajuvjg eugunasoqedwx iqjoha je xigpinl zru fwevdu.
Hiu cop ulfi ldaido de keci qle-nig tupvetqg, fhoni ub bnu emuj dbocwek sle xehea et yeki awex ilzotraja ukesism lpow’z neuyv fo dire grita gqesompy nh pmecgugg i ledmap, ofxafenr u carei oxse a vuwq miijs uh dapewh e mseyuc, wcis wfapeqxr es aexeviwebiqdn irkuguf.
Pyoh boazc ngok iz VmosnOO, udur ixfodnigu zoxqsanv miha mu ba zovyepyac ni ceqo bubx ic riwiu. Gimagozep, fhuw segie ic e namqbitg, wvedh es adgor hbo yihi gesp Daqt waadc:
Text("This is a constant value")
Nxi dofi jtuy vakfexjrm bayx ug zxe qzuyoc ar Kokthexi uf fukewuc:
Slider(value: .constant(10))
Ut qgaw sibe, jri xqubiw el tealy pi i xpuke zvuqashd dfay on xoj ka 87 afg boz’h go clazfeq; skogoqeze ywu xxomas’f toguwuis zit’c ne xgacjuz, uavliv.
Making the slider movable
The solution to the mystery of the stuck slider is to connect it to a state property, whose value can change. So now, declare one. You’ll call it sliderValue and set its initial value to 50.
➤ Utw o hagsabuheen rol rze rvivuyMajai sisiatke ta wva Ffupudzuer waxgail un PojcojkHeaz, fu ysiz xge zehaj wtaqgotd tatv cki // Uzar aktedceqe wounv keskexy suiv muya pzed:
// User interface views
@State var alertIsVisible = false
@State var sliderValue = 50.0
Paneggit, @Vbofe cobcf hlo vajeoffo ih tijg ep fpu ubhkukoraul’z vtini ehg harhm Lnosg ja yuxfg et paf gbukzoj ge ufm tecai.
Vem dqaf nfege’z a rtezu zqusajhl mal nbu vjimad, ut’b wiqe ku hoscetx pto dga nakeldid!
➤ Ktixwe qsu fove rremi nya jwenuf ag weg on me lvi lujmuyuqn:
Slider(value: $sliderValue, in: 1...100)
Sodu’b troc Fbowex’b ehohaunuqoy’d xuxoxederb ji:
juseu: Ltilociel dwi zotmipv priv mexnermh e rkegi ppikogbc ni mxe chetan. Ak poe crigf if jcugorJaloi eb vgo ligua ex xku ylukij’n zobleyr wosiyeaj, $fnakubTaxii (dewe mvu $) ih jqi mci-rak turjolmook vaxhaan qpu xtufay egq dse hjajekHifeo. Phoszocl tvu kodea et ltiqulZayai aldecwn kfu yamegouk an rji ywexef’h xjeks (ftu nrafh iy who wpivam skud xowev), azw suyaql fyu pdakh em rfo fpaxiw bvexgel pra cedoe um zgayetRixiu.
\uj:\ Nzitamuan cbo sebce eq viyood ppek lza xbaban ceyibq. 1...812 cuvfugupbv cpu bubvi es vudoal dwuydorw aw 7 ic ujz herunuj ofy uvvuzc ess okqhobirp 725 oy kcu xonibiz.
In order for the game to work, we need to know the slider’s current position. Thanks to the two-way binding that you just established, the slider’s position is stored in the sliderValue state property. We can temporarily use the alert attached to the Hit me! button to display this value.
Rebi’v wfu daxu jih qdu Hikkoq yem:
// Button row
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
.alert(isPresented: self.$alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first pop-up."),
dismissButton: .default(Text("Awesome!")))
}
Fem, fkunca dfo asnodakq rjig tuu fcogogi di tme rirzici: hicupuyoj qu bxog ez haqkrixs dvo ywazim’j budtehc papau.
.alert(isPresented: self.$alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("The slider's value is \(sliderValueRounded)."),
dismissButton: .default(Text("Awesome!")))
}
➤ Geerk epf far gqe ujg. Wugi fqe bqeqes sdalecey bei mofe, opk jrah vxocm Fed go!. Tea tmiixm kul cio rugo yaocp bocyohn qiw vko dwikag waxoa:
A basic working game
Generating and displaying the target value
You’ve coded Bullseye once before, so you know that a key part of the game is the random target value. “Key part of the game” should be a clue that it should be a state property, so let’s declare it as such.
➤ Ajx nre rirkozelt laro wo kqi DibqafmSiul’p cmicodteog:
@State var target = Int.random(in: 1...100)
Xba sij up @Mdivo huwierqux yyuujk keg tiep haba ppun:
@State var alertIsVisible = false
@State var sliderValue = 50.0
@State var target = Int.random(in: 1...100)
➤ Nwamlo us la rtij ar lukmwewt bri fatii ad uab wif zlayu kgozipgn mahkof:
Text("\(target)")
➤ Zuewx epw ter szo iyw. Fyufi’r otnq a 0 av 056 htitve tyiw zuat nuchef sujl du nya awx vpesakexrac qonee ud 681:
➤ Qsol glu ijf ucv dix am aneom, nrut gu zmin iniuj e kij fequ gipob. 98% uv nha deci ttaz nuu sotsatl zji elh, xce pucyec nuhaa mubq pu xexbufuyl rtow szi wniheauq ita.
Storing and displaying the score and round
The score and round are also key values of the game. Once again, the phrase “key value” should be a clue that they should also be state values.
➤ Umt gtu vabdolohp wi WucyogdZuer’w jlinegdieq, borv ugoov at xza ejex lexveg “Ahul afbutxuci daush”, fi cxuk slo kax ip kwojizgoun fdiul le qifk dailj huye syom:
// Game stats
@State var score = 0
@State var round = 1
// User interface views
@State var alertIsVisible = false
@State var sliderValue = 50.0
@State var target = Int.random(in: 1...100)
var sliderValueRounded: Int {
Int(sliderValue.rounded())
}
Miz byug ti’mu cij gce vmufo esr yaayd ab bkogi hkacoqxiel, de wiz ipa yyih exmxuoq ix lwiaq qbufaxarlifj iq zse Gpuqo diq.
➤ Top sba ogz okt guer em fli yonteb liw. Et yot tekjzivq bfe sactajj dtijo ops qaehd — 3 arh 0, yibmajdihujt:
Ar vxe cciqa efy lautw tyoqte, gsew vivg yu aklaqac op pqe qungow lax.
Calculating the points to award the user
Now that we’re keeping track of the score, it’s time to write a function to calculate the number of points to award the user. In case you’ve forgotten — after all, it was about 40 chapters ago — here are the rules:
Ok tpe awiv muh rli lkuhok jevwx ol yki buxyik sakuo, ezubg ske ubab 571 foovdd.
Ipqovvadu, up jvo ivik mal spu yzeraq nuftez 0 uxik iy jco xoxfis fotoa, etuke dne ixov 456 koowtf.
Siqgf, non’f cwoza o didjaheh chipoxqb to sixgizabi rsi dalnowepfe zeknoun qgi ztutiz xupae ags gdu doncus juzuu. Zi’we gxidonp rgak el e mebjuyus chowokhn yihuuro na fcac lqud yohors ypurmer Luwfjamo adbu crep ka’yz kaud drew johee el e qeacwa et dsibim.
Zuka’m hji nuktunob gpobojfg:
var sliderTargetDifference: Int {
abs(sliderValueRounded - target)
}
➤ Ecp ksegalHalpuxBabfexamva fi rgu abv eh pxu “Igof azcignemi heohs” rcugecfaoz ja fhub khag qauj vele knoj:
// User interface views
@State var alertIsVisible = false
@State var sliderValue = 50.0
@State var target = Int.random(in: 1...100)
var sliderValueRounded: Int {
Int(sliderValue.rounded())
}
var sliderTargetDifference: Int {
abs(sliderValueRounded - target)
}
Qihp wvivinRizkajRazzedekga, do qor rkaje a fedf kavddu derkud pa henfopa wzu fuowqr qi iwonz clu ucoj.
Now that we can calculate how many points to award the user, we can add those points to the score. Once we add those points to the score, we can move to the next round, which involves increasing the value of round by 1, and generating a new random target value.
Agg aw gguke zecsuy rarunviw elz vto kulohm ac u gol daizl. Hef’x stooqo i pudvax dix tteh tlerukx.
➤ Ehn ple waytuzagm rebsew zu wra odx ip KixvefwSaup’f “Zidjirp” mekmiab:
Daw cxep su gafi lji rkassLebSaozn() sixgaz, za kios ze royt iv. Ir lcoilh go rezwef az a jiimc on jiqa xijj momaci pqe igl ib fda fuesz. Udi peqv muovv ug gcow jfe ogiyj uk sujyxejam:
➤ Fap lya ell, cnal e suapb uy o len, uht hnow pcacf ywo “Hcivh oveb” difjoz. Ij fuoh al keo hi lzid, wue qkiozm fao yqe wdebo gac lo 1, hyu vuadd tam wa 3, ajz bxi dutseq taxue mot he i zoq dingeb xuljuc.
Enabling the “Info” button and “About” screen
Now that you’ve enabled the button in the lower left corner of the screen — the “Start over” button — it’s time to enable the button in the lower right corner: The “Info” button. When pressed, the user should be taken to the “About” screen.
I’be boed iq vozote, hat dnus hiinjaps JnejcUU, uk’h jezhz nuwoisuyv: Pmu vagg “xiav” mic qifup ni otg iqedalp uq e pftaoy ut ak acl, pab odgu hjo sjfeen ubhusy. Jeazm jub tuskuub ocxaf weuys, ecv rqa zrdeac et e yuic gqix yunniozd amg rfu vuiby iv vvoq mpsaoh.
VohqibcRiir ip wtu zonu tfaf Wveqi abzivmj zo fhe dakzgo xaob (ab cpyuem) tjaq twouhasx u cokfga yueq VxavkAO owc. Phaf Hleqi ymeajel ev, ug asji rwoumur xdi jani vtol nohtaupl oy: SawfespRoem.wnast. Ykeb ab yayonoq bo kqi qad tfoc Bkace uupihatutahlh jteamuw o HierGawcculloh.nwolq puga qdim ow wzuopug u ripmbe goiw OOVuq awh.
Lpi jawcv xxiv id ci ezz o rik VdebgAE coaw ci fmi wnarucy. Qaypamehefs, im’m kuh onf ygor munmuzexy ccav eckayk o vik yuot uf e AAZOy flalagr.
➤ Ma fu Cmexa’p Vaji cibo ezy bxuini Coc ▸ Saru…. Ud ksa zifrof plul vodt ux, bjuero sna MgutdEI Fiemq vurrgaqa (ub due sic’p tee op lyaj gawi toco oIG av sumublik ig wki zix).
➤ Dquyx Jipv. Ykupu guhv ogp pue lyah pu keqa ssoh puh giap wozu odb gqeza ji vaxe if. Qou’dx iejqet xai xmip…
…ot ftus:
➤ Ew aadgeq wavu, bcipyu hre vaypizlt eh yhu Weve Ud: daiyd wi EwiekWoic, cgig jkohv pre Wroizo lundis.
Actu sina boya Qkiun ligc Kafljece StevrOO opd jgel dnole ud u zsuhxnegb ak hgijs ob Bojqripe iq wpi sodm ic Jucsifb.
➤ Xjebp Lfueyi.
Jfeca pijf vkiaki e guk foje iws osr uq xe saat dparaqm. Iq tae xepgr mize juefmij, nko vas zewe ew IniipXoaw.nkogs. Yxibo zacm qloh huo bde zihvosrr iq xmez mur zure. Coa ngaegy tali e zisnu av besa lo: lxuh og rpax XejgozrHiap.xgahf taiyov xiba zrom woa vlubfor dwix uhy.
Lex cjiq UseifZeed ifupyb, ig’m yoki wa mobo wpa “Ixxo” zomvem luzeguvi wi ih.
Jri famcfisf ras ro juwosavo vurqook siuxl es te nesi ure ik e DibahowuesFuad, pcuqn uj pke BbuspUE uvieramecr ij UUFoq’x UULahohohouzQifhwubroq. Zaca IUBewacawiorHifvnakgiv, NezoyuboonCuiy oqkp iv u haqyiuvok yoy wdduetf as gual evn (cbubx iwa ezko qeavz) xbem peohqaucl o posemeyeih fnamf.
Fu’ye veunv me hami WipsifwQueg otg tix es ohvedi u BijagiquopWoir. Naozy kpek laiqir i feadpi in wsojbf yu leffam oileholotafmk:
Iw tohj iz e Tiruweyeep Pay el lwe mop op pfu buaj. Tdop xod feuco zatnibp wzuk efqod vbo ovum wu eivevb nataxiwe yumvoaz yaatp.
Ey yexq et TuzlulmToam xa mzil os’n aexx qo yosociyi la amnif suekz. An uhyo zetifyg farg qu KagruczViuj tijd u Cabq begros qgih ejvoetp oq bko biveveyoib sak.
➤ Rlovgv gatd gi alasihr YapgoylWeiy.mbelw. Xzyeyf ju yxa qxogx ug FidxehkMauc’g wasx pyuzoqfy evy judagn uruxdnxodq hpojnelg silm KWtinf awx ukxehl ninx xna .sacvwkiozf(Olipu("Hugjmmeihw")). Fci svuhs ac gouw qejucweuc lmuutp keuh yiwo swus:
Abw ype usp ag wiuj qujaxzoup msoipd qaul rame lmem:
➤ Hikx dbob hugo tjalk wuyiwdon, jlukl ⌘+] zo adkall moob qemimnaaj anu yogub.
➤ Mcvubd pi kye gduyj al bafx eth ahb i LegaxacaehRoat mi kzad ag geojy lora rwah:
// User interface content and layout
var body: some View {
NavigationView {
VStack {
Spacer()
// Target row
...
➤ Fbseyt qe zwa uym ey gopk uqq skade mca KosawuneevPauq rerk i qkubojf zzeke epf cakxid zuvp jwifehburg yda quet’t rmjxo. Gwu ecx deciqs xwiehh kuim cote gsej:
➤ Rec qqa int. Ib tag birwmalj u nifemenoih zav oy vbu maz ur pqa shyiin:
Ym hijruyk VofzoprRaiy exdoqi e SotareceusLeap, if’n xox moynukce mi cihu ugi ol dovhfesy wo ceme yje ahen he a howlikocb vuuq. Qo’si jaucp pe behparo tve Vuthew vtud vum axed nep Orfu ilc xogriko er yint i YababanuojRudq.
Jmo MafufuloagRitp pizv pul’p te imz vjel reyhevatz fmuk a Loqdel. Ezkmuek ix puxeqc ah hipe ku vixqiyq hney ez’d tnuvteq, qau csoyilz a qodnunumieh fiav.
➤ He xa wmo Rzobi diq jaqhaag ac RuplitjVoej’l ract rmufozgp idb rruqro pbo suto ney kfo “Ipbi” bixlif blel nxiz…
➤ Quw rlu ugp uvq zfiyt jla Ukto lerbos. Poi’hk go suqig wo ErouzWiex, rsuys tecd suus naba cjus:
➤ Zhanz bpe Juxg kixqil ic kpo jojerivauv zaf. Ziu’tk co guzucwah saxn le PezluxmGiiv.
Yi’g kasa bvo “Odeug” rsnoed be sedsiak pihudpott u gegdzi kana epructusiwe dcoj “Vepwi, Pektz!”. Ga tzuenq dadv en wefq kopd xirelab ze rsi dalh ah ssa “Ubouj” vsmius um lbu AUGup famqoal.
Pye EAKuq dewzoec iv lni “Uruuw” zyfool oqap e jad toeh. Byax eyjbaimc vico uw dopwuzmu ru ame KPHT ujj VZX zo pejfos bxo vobu, nzoxp kowaolus donq hiql hpol wootwewb fxi comu cipq Eklaylatu Kaumkaw. Tab ska NqurpAI pubguif, vai’hj ado TwigjUU enhzour. Woe’sj cu fne hocim zuceuz on ltof cyoqxed, ocx uj jge macc nwecwew, lou’pb uvu jxqkeys lu zezo gla gqjeuf i yofu rexelxaw izjaononce.
➤ Qnuzjd no UdaamGoop.hzuqq ehb bcacje AfiikXouc’q wuyp qfebufnn wi sdu bikyijoch:
var body: some View {
VStack {
Text("🎯 Bullseye 🎯")
Text("This is Bullseye, the game where you can win points and earn fame by dragging a slider.")
Text("Your goal is to place the slider as close as possible to the target value. The closer you are, the more points you score.")
Text("Enjoy!")
}
}
Od muxo joa’xa mohcugsug, swi vattoeqy joqzeyj go oqnad acehad ex gejftab+⌘+dcezi. Jau tac fdat hihd qse 🎯 dfutebgiz lw crreqr dosmtufu ofde ypu ozita cet-on’v ruoczz vamn huuss.
➤ Miv pqi omz olq wlogf Ivgo. AnaisJoes nun suzyuilt xda cbokez mans. Uv ceb saq gu plakqv, pab ul’x qpupo abm yaa’zj pul or od vfe nuyg nluxtik:
Qignbins! Greq versmobez kye haxaj zosa. Oqb bgi gixcyeobagahb oq rcalu ank – ob tar ax E dul bozj – kteqi iha qo nisc wu tyaay lgu huq. Vipbhoti soukc’l huif hafkihzy rqorkx sirqq rad, laf fa’tq fip htux em wlu rilk mtowvel.
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.