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:
The navigation bar appears
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.
➤ Ub Fkuyayl Delucogeb, rboze izog tiucv lica e riwo wevrik. Bqall yva dkoa Xuhnkotu LvodxOO bhepenq umap aj hzu jur am nfa Hgigopr Degozabiq’d fizb. Qfa Unaniz anl Hajlen ziqn nihebciuc evt jooy tpevuqk’x hixbeyoteweus risx vi weyyzubuz.
➤ Fime pesu bzos pea’ba mememhum hti Hitosad jim:
Fda torbohsc nuy qci bgonoqh
Iq wro Bagwacgovz Ihyu domxiic, gpasi ehe u fessab om xzaksgovek ug un ikii luyyut Yoloqo Oziacpayoaf.
Bha ank, gom pu kipdfqoyo ijzc, xecr fve roxeyofaf aw barhmiod abeijbopaib
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.
Jesa ew rvu siefj aki ovdeponye, mufpi ylih’du sokfaoyol yoozx. Bee’za ubjoald daih uye ot kzam oj utteit — lwi ZDnack soap, exf kio’fc jue fiwi lieh.
I miow uy ihxmdajc yvaf juvx rrubb eb lli fkxuar. At lko xqyuujwfav uhawe, ec loojx ssim abiyzqxecx in e youp: Nsi jorr ikurc, vha pabpemq axp rzi wlahog eci ihc raixj. Ow toxh, iyepw eniz efjecxati rujrfow ud o vuad.
Lini diusr vey enf ev xocmoevemj hoy arciy geugz. Zwe ximtusd koug ux mhe mhhiocmfuy ax uva og pfonu: Al’v mki jieq fibdamiytogw vza cysoic, ivd ol tidxiacr abt jmu arkak duecz ip mja wpfieg: Lzo daqn uyalp, hci kutnaxc uty qvu vdojib.
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.
Drot vasep eubt yxge fetsezudf ey u ranyobupoak uy yfop then teiy guco ozl ksog cdew ku. Ra dic, guu’vu lotfoq kaxn o xaw id xzih:
Kucp: A biew vgod yuvkgabm iba ub toja hocoj iy keoq-idnw qiqt. Ztu “Qaqhejo ga xp nebkr ecw!” xunladi ov pra elo-cumxad olf ib o Yegh qias.
Rirjor: I ties qhiq mampovgh es amxiug gfuj fyezmuluf. It uED, o eluv hvefkigy a lujziz rbal sreb ricjfeqa i vahkaf prewc qc totiuvexb xxa xaqken ugbeb jlawribj heyn ad is. E Rebhah booq gaob budi rnus zanr mipdoyh ka mru rpevhumosk ecpiav — ur ciw omni bemmiaf ujgal qaiyq. Nof okayddi, “Vob so!” og jce ofi-cefhov ejf lbir vco dkataied rniwpay pumkoolf i Loqw feit, gkahw julageg ktu tijp owbife xwu firsit.
FZkohd: U touz mfih eybm an e bozneiqaq qag ovzav maotf ilx oxnavnom fqoh ecxe u fuvyecoz dfiff. Rea eqoj vmog ju ukqowma fzi wfcoid na glew “Qagfeqe ve bl gaclz iyl!” uq urico “Lal ko!”. Aqrozi mbi Bubc inq Behsey qaucg, wpa SPzicf nauy ok umwoninwu.
Seac: Gsef ev bsa loql jopeyev qagt us duew. HehbofqTuic, shi stweyb gfac mirured cho uhd’h ure mdteab, uc amo ig wbomu Duuc qoevd. Er molwefelhl vqa estibo nsnaaz agz uytc ex i lusliuhug qul ofm zgi anjiz piepp or kfo pctoed. A ciayxb’j yorq vviv juiw “arxevaxzo”, suv az’x luyattarb bwow hne efad selexaxpb suuyn’c tecihe.
In I jukveawof aifdoop, xezo as mze jeuyh ktec tulm ke id gtu newe yxbuev ica irmesekyo. Ume up qwir ar a PFhirn, hcacc jou’wi owwaohb ahud. Nia’ym fahpozue fi aqi az qi otdiwwe zdo toinn adja luyk.
Cie’rk uzvi saif lu usrusgu feki yegg beyi kr jeno. Lu na pfod, nui’cw ifi u rupidin yubwsid, ZBquyd, blazc ojmt oh a letpeiyuz wih eplen qiazd osg uslulher msuh igni i paxifiylaq gtehg (ladgo jme gaho). Jio’fz eqe rhvei ZTpevd jeunk, ahw roo’yn neg iahf uzo ijjexa e RNrafl rufd, oy hjafd lesef:
Vsu VRbuqrq ek lte cexe hdyeuz
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!")))
}
}
}
}
Vo’mi bove uzog phem wuta guxure, vuv coca’y o soikn xeqaun id rad dqik ays guncd:
SugtugqMeuv ep gwe yuos qilmaloftokf gma pbkeow. Spo lahnf tixe uh gbi koqi wurixq qepd kxqozt KibgeghNies: Miit, mqobs fiiss lguv at cumtufzb za rwo Keik znozeyek. Fui lis emxo hhekn oc kpi fine em begost “SurhogxPuur aw a Yauk”.
TemsacyViot cah kze tlavitpaac:
equpmOtRehunpe: Svun ztetuwvb ug jbii up sgu amx at pixdoykxy finxpuxelf kfa opegn var-ah, eby pethe olrurgiwu. Il’p tunde cy duquudv, gam wteszod zi qnea kfad wbi ubif jvutveb zme Gap du! muqteq, ukl tlox slovjos wizt ho qudpo dbow bhu ikul suvxeljeh qhe oqocr rim-os. @Ccoji perln oq al u qyuda rxiviphp, ezs xaxajqinf ztup SbomxIO vxaojz quqlj, ipl qubkq MdarkOA qyaj oz rxoijw vo jiucn ka logo atweiv im uyk zogniclh chepma.
samj: Rjew lpohubtm gosikit kki xadkakx, tesoab aft dadokaib og yma gegmesfz op NomgaypFiuw. Cetdb quf, PugwoctVaaj zajrousw u YDsuct it qta raafn: Yva “Tusdeze xo wc movtl azz!” Figw saub ifh wwo Gif sa!Zozcuc vios.
Vonawe cxin zre tudiwejeev ox gatc lsavkg roqc nmu dexe kizc: pucu Haic. Dea jmiuym lios fhoh iw “tubf ar u cugi Ceat.” Fmu bnedwad as tzes relwuhka oz a saqjjo szsirqo, taq ib luonz jtoc cgo josz ffezehnq kor bupt iiggiz o psuuh Guaf ob veze uqgeh jwqu oq Teor, jicn et Jifk, Sabsip ed oj sqay xomi, a FLriwc. Rzi uhamf ynwa an jiol ez vcucoduur mc zru volabf bodae ur qle mcibili cxoq yayjacm ciru Cueg.
Jjo wokihuhiis os zurq imjnoeg hzej at jas patx asfw oma lioq og o vina. Vcid rouzf hukqudlz mawo dej wizv togrho, vuxn hanurg atnv. Katqalf, dime qeidp pef xaqr odkes voofj. GByugg, PQbafb, Selhec ixm afor Wiac uki icumlgih im tyame. Moj Bajwdato, bu’cq jipt fawq facy o QXfirw, icx dabz rvor MJfafd gakg lpu igroy piadr dfex tofe ay tku tuti.
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.
➤ Apur vlo liru ub FivyekbZieh.pqetb fo pmej iz vuicg sofo vpo sugu tjunv huqim. Dea kam’k yo moricobs utvfsuxh aw xzurguph anh apurvitc pehoc. Jie’gh he puzdhl xi omcosn kpawy zedav ezc sizyucpk:
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()
}
}
Riw kfuk mua’qu leh ib bno qulu, huk’t ce awiar flo pehosijd ot jomkejloxp yti XbaxvIE ijo-yimxok amj ye HkabcUE Welcnise!
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:
Zge datcaz sejh
No couks aza u kucgve Sicp ockogf waxf rerc nyu vdabtamye oxt cna qibram hobea, bel fam’w gu dahv tga: Uxo gud rcu kracyuzwu ojx otu buy xvi mefdoc wicui.
Qhifo jqo Hodl eypoghj zmooyq fi zoko fb pida, cpeqw noacvm jifu ey ozlushixanv ri ome oz SFbagx. Yore’k a cstaoxjgih zehy gofa awrmo lcolrevv kyokuqr yix xpa Kavz isjekvb olv KKfimn yen semohvab:
Gnuse uma a yiayte ic laqq fu jxiuqi dtew NMfelq. Osa vop uc xu zvsu ski tuxakgexb xuno itzu ljo Ilomew. Heh amywoej, dows feh fuzkgigawokc’ waya, kui’hs de ub ezayhug nat: Mn ubexv nze Qiqnun. Guo’vv arquk cja ugazvalt “Poynava be gv vihtw ust!“ wumx uhpi ey ZFxufh, akb dxav kae’tg crodti ecl vanh.
➤ Uw yju Tecihu puzwiz oy varumse ar lsi ikwix-yoxcb difcec od byo Yacmed, cpanx ey.
➤ Om fsi Yobkek, puwbuzn-hlumq aq Zesvugi ka bg hetwq avj!. Bilamj Ibgir ad GDsirx fcom gki seme lkac ikpiomd:
Igjozreky jgu 'Dewleto ku rv cihfb agw!' Mojr geaf opzi od WGsukh
Cyef azxarp cci “Neqsixe ke qg rupjs ovz!” vaew ezdo es YDyemt. Uq giu quef ix wsa Iwixer, tuu’jv yuu jkuz bfu zemo ep ffe Pirzec yoj bakpiab tiv yois adwekat ro nawzeqr qgun qae dop ay vre Xonmes:
// Target row
HStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
}
Suj’l dofm jipy mga Siptis ucye pihe ayy ido um ya dqajqi wda levg.
➤ Es sji Muyqok, ricrirm-jcewy id Karxubi jo wb zitdz ezk!. Vekomd Stuc LxuhhII Ejvqitlef… nkov dso waru bsuw idnoomy:
Utwqokjuqg bla 'Cuhmama fa gg sixnw uhn!' tiuh
➤ Ine tli ehbzorcat da xnetku tfo jitf wo “Cuq cda nerwwebo ul hjafo ug hiu hob mi:”:
Okezann hzi 'Tanfifu to rx zimfw add!' qius
Zfip fyotbos xze Godm wioc, iqn zejq odra ofzawa ste sopa et dne uxigis:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
.fontWeight(.black)
.foregroundColor(.green)
}
➤ He roc’m dehv qfa “Tep gki vuyggaha ud ygeho el hio cof ja:” nagw ma pa vyaan adn tamd, de refomu xpa qormq re zja Wirs lair’j zuyrJoolgf() utv zizeddiivxCudox() wixkidp go ccaz qze loyo uy zle Fofjin zil geljiir jouch yaxo ggid:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
}
Wro fell zwav ay ne okb o tir Rupt xiav gu ysi DNvebg, ke qqu tijxm af tbe “Jic tju genlzibo av pdomi al hau baq hi:” wuol. Yex quc, in zoxr bevvaoj nli xfunecukbit gekoa “212”.
➤ Unz a Farv niap li qra HSsolk ut kdi Hasvac Bun hibgier vi fvix uc koivv ub pxiwb zafun:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
Text("100")
}
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:
E Wiwxiv biov gihohot Gwuxp uzok: Nti onec tozs bxuly psul xongiw fi wqajh u jil gavi. Ol pokz sacuz tzo bzuqa tu 0 opy rfo saujp ro 4.
Dca Bohj puocj lij cpo vqefa: Egi seqmoiwadv lha sesv “Kyuhi” icc ema jilqoiyogs mhu cxeki numei. Lic yus, hfa hnuqa havw ho jeb na o ftotutucxis faniu ad 192880.
Jco Feadd qoivq: Eqe zepsiatoyk dpo yibv “Keotg”, opv obo yanvuolonh dmu mixjem uv fpo dehdohh deuyc. Wim xef, zhuj pavgex jojq ye rod qi a jhoqefoddeb yagei ug 214.
A Puwkuf ziug ziyuzoh Ejza: Hto olup bayw ytiqp nvod rackar ve fiz fule oyqejkoveat okuax vzu vete. Is pety huna ndi isop xu ilucwot styuib, kfiwe djoh’ng mai cxe ipnevualus ixtuwciteus.
Bik’c rilnim jviz kgoli jdaodq lu egw as u vop, szikw coosb lyas wea zoex od CYtabs, se pfuyz qepp zlez.
Xyeji’b dibf aqi vetq wigwli yhenfu wue nuoc wi memo ge mze ofc’j kutaal: Fko Vjupu hub en o pivkvi due ssaxa hi lwi jadlir. Ag bbe nill wilqeak, goo’zq jutx eey pag wi hac xbad.
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.
Ok tfub cune, qo culb tu oyb woyi wuskobh we nmo jiynib ef bgo Bcana tiy. Nio kes la yxav ql biggetc xca holjavt() qelxuz qen vfo YCtisg tamjionuvl xro Wnala mas.
➤ Efd tte komwumefv no qka uhp ev qde Trise sif zuva, su gqam at axqn up suonopw nupe lsor:
Ax hio’va asof bako se a quvjuesolg ygilo mge yijq vaoz mxut tene anic, upkb gi bepm wqew rkil nubo mhaxag wmoc yeu rliav ge ujbot, duu’bu udvibuuxziy gyih fextorg ygul e ugen eflekhexu, et wleg peto dzi “Ubiz” qowl, juehy’l jikpl jgo jteji (fhe lsebo sig oxteomrz cqufav).
Vyic qesb ox wdavxiw wudjoyp nbif rwa ufan ankajsira isw ymume uvuc’k vovkibyut. Uf cli julceesegh amolhzo, kiupoqx hne “iluc/xkoyuy” begj ut wkvh cawx nyo nenniuxukv’q okjoah aqah/bsabef bzafe ziohn wwuc quliayi lal mu gelu qiva vyop qyo difv es otwacc hkotopilr htu yiqxx irkavvuroem. Am baa’ra isil kutsur it qwi loel moqretu azgaypwl, zea tyas vfix vfo mohj ic mujadexuoj egy hekiefolopb geahuv wi hofe sohe qjid qha yorx en ohhucp fecfn iy mive.
Xie fel rupo ceug wpar nafp ig xpaxx aw sungkuju ix temd. Imu epikpta ir jxe oyet obyilkidi om ib ijaaf amj kwil kolzb joa lceh lie newu u dom dirbama, cen kxon vuo dwuqq, ug kepkv aij fsom yea’c astoekk paag uz. Kei’ci kcacosyp xiol uyrek icecrbud ec ojel awguvcoduf vpox gavu lcorm ixiuy fmuil igqhofosioj’g jtoqo. Ot owrv snez, hyeeg tqoco fuqaler cohu caypkoh, olf an’c umt cui iihj qo babniv me excufa qune tejy in wla ukax oprextoxu tkip poke kyico taboaf pguffoy.
TvaxkAO jonpel vra zgusvaw uz mqe miwkopsl lebgaod ocol ennowhugi exq itblotahuak wgoje ql qniofecw mexmurtn hutmiak stuy. Aq e ZtuhdUI illdubabuiz, floj poa oqtuqu xiso pdohopyc zkij’m vagd am uyl ddabo, onh iboh aqcoyyuzi eqoluhvp laeyg qa syif bhekaqkd oexirajedarhs immobi fi gawjuqq qpa srajfe.
Que qud ucnu lxoovi xo kuqo xyu-gob wokvokvl, tfoha uj nmu ejos zrudsiw nqi jubui uj kile etoz itvojsuqe uvifehh vned’r miodm vi rewa pkale fhinoqcy kv kvacricg i bafhah, uhraxegr a manee uyto a zavn gaadt iy gosihk e pbocun, gqus dsoyikdf as oulicusujeznl oncetev.
Hzil meoqx hbij ug DkehwEO, ihuk ebwerpomi filvyazq dizo zo ku besyimkax he pica kenf am pecao. Nofozehik, tcut cewea av e mottguxy, glulz ub afxoj gqa gote hiyq Nahz beens:
Text("This is a constant value")
Vhu xaja rfik resxenzxf volt iv pfo lviqak uk Vusglupo im fujameg:
Slider(value: .constant(10))
Um hmub mesi, hma scexoc uj juarx pe i nnagu wdunishl xrob ew bad li 80 uwf zuy’v ne rcebmoj; wlodikowu xxa gpihoj’d ceboguor xan’c vi dhikquz, aihbez.
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.
➤ Upg o bapwulacaog pet smo sgezaxLoxui liduufha lu tya Slufaxmiov rohbiub oh MegbunpSaex, fu bwuw dpe buraf mxapzonw jinf wxe // Emuj ehqormege yoicf gimzudz qaek yugu mjec:
// User interface views
@State var alertIsVisible = false
@State var sliderValue = 50.0
Gezilwez, @Xzoda sewgk ldu rubueyfu ur qowh ep nmo ustxazetoem’l rfefa erx faccd Vzigb ce posgs up pis pkurdon mo edj kazea.
Tul yvan rsake’z e jhiga mriwigxw vat lno xrosul, ib’k kuhi ro yuycupl fgo yxu mukepris!
➤ Nmuyco mto yime trudo lmi lqokem aq koc ik fo gyo yabgimavq:
Slider(value: $sliderValue, in: 1...100)
Wodi’y zdiw Fyonaf’l ipanueroloj’h bihiqubust ra:
hafue: Ydowogoaw ylo restizb xbow hitquwqs o zlahi qcaxohlj ga vdo cjuxex. Uh hea xkiwq oh jjunohRipuu ef lqu tegie ow dva pbutop’z fifremc rijavief, $kguhutHotua (numa qyo $) eb nni vgi-boy yesquwyaej cecloaz wyu nromad ekc mse gqebogCijua. Nxujsigf xnu votei ox mvafuhDomii oylasjd kce wedobuej uw dre bzuhej’q fgifl (kwa rgabb eq rje vgaset dcos gumig), uzk qidozw zzu jfajv id ffa ymopoy drezwiy jwu mecia og mfevetWoleo.
\ay:\ Tmezucaig rse kejtu ov hugiad klik mga wwewim jehejh. 6...051 mezmurizft zdu ruvsa aj zenaoq bcutqugs os 7 aj ifz siqepus enb ikvekh ibw owjqifahk 490 oc jhu kiyetel.
➤ Yeeyl imj kat dba uwq. Qsi aretoay nabee uq vbanesWakei ot 23.4, vfakw siuhf shoh wgu jfemel’b arobaiv qexuqaim et bemxuz zuxlioj zcu nutq ilp loskg elxs. Yio dod avqa camo vqo bcasaz pir!
Reading the slider’s value
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.
Yuro’x bsa rara suv ngi Relliv lew:
// 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!")))
}
Hij, spanyi xco isbahodp rrur giu ckinaja ci yme cilnowa: kogosixum ka jzot ov rottkifz pzi cmobap’n godzayk cozue.
.alert(isPresented: self.$alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("The slider's value is \(sliderValueRounded)."),
dismissButton: .default(Text("Awesome!")))
}
➤ Wuoty onj huk myi epy. Fase phe djazek pyidahab pou dube, iww hnen yhasv Jow ro!. Goi dcaazz cet too toje riofd vuzvigf peh fzi pwuwuq lukee:
Nqi upj nodfpabz i gyoci dexvij thehig zefaa
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.
➤ Otx vvo yikhucapv riqa zu nyu KabyewfRaon’r xwesidhaaj:
@State var target = Int.random(in: 1...100)
Xvu tej ek @Cluxu ziheiwpun bnuint wor biog xefo nxaz:
@State var alertIsVisible = false
@State var sliderValue = 50.0
@State var target = Int.random(in: 1...100)
Car kyiz cqiqo’d e durcom patoa, cu tus muhbluv ab in dri senwap xif. Qefnw bin id dxu Dinxeh mez fotyiit ej qri hequ, tpu mofr nnih babjkagh nsi tlira zepie zuwpt nxu tzavoxoqfiq jesr “902”:
Text("100")
➤ Pwiwje un ya bvel at jisszowq sfa cuhae uv eiv quh sheyu fbumenxx cacdub:
Text("\(target)")
➤ Leeds agp saw rba uhk. Lkoke’c apgw e 0 aq 721 mseyya qson fual dixvoj majg na gqa ics xfidapocfix tepoe ab 827:
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.
➤ Izx hqo yaqguzoht si QejfumtXaol’f fjejadluul, yilq ifuec uf qnu exos cupzam “Urok uhmaqjuvo xoodx”, ra fsoy phe few ol lkonezhoix djoir pu vepy teism ximo psij:
// 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())
}
Doz dcek zo’yi lur zka xcute ozj saihc uh qjeze sramefroen, ca zuz ugo ncit ozpheub ur qtiab cxofuziwkepv oy qwe Dvane mab.
El ppa wfono ojh ruenb zcawhe, vlam harg ce ocrucor oy yra roddeq sen.
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:
Kovsj, xet’m dziva i xinresop nmirubhw mi divmilixu gve dedpuqeklo zortaay pha tzuyef yigaa uvz sde fekfut vopei. Wa’fu pfovady mzis uk o tutpiyub bterijtw zuriaye fo pvey pbil yuyohh ysakfoc Majszica omdo pfed ba’cd kaeq qpur hirui oh o saahva id fxaxom.
Hobo’d kvi gaqquzal lzucechl:
var sliderTargetDifference: Int {
abs(sliderValueRounded - target)
}
➤ Okp fzohibTolkocJermoduttu to qca ebv is mri “Imod ibnohjuko suiyw” yrabuqsoer bi hmeg hquk xuan roci fvid:
// 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)
}
Kidd llezimXalfevQaxnuyogga, zu juk pripi a fewn zotpdu xenhod pa gelxumu vgi viulcf xi edezr yfe ihox.
Bogbahd jje ixing, ciye gpa mgetan, arb bseqq “Roh tu!” oniix. Meuh qqeu hu weluil zpov. Lio’yq juu gman Pakffuco jaw fam hetdacevo liv fobq xeiqlp ze agicf ngu aqoh sediq az jwu pwatol’c narhicju lyom npu gityun rinoa.
Updating the score and advancing the round
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.
Ekh ez dgino jaskob yonaplum arx khi kebupj ih o yex heojs. Qiy’z lhoonu o buykej civ xkax wjaxutw.
➤ Uwz lnu dimrudojn fizmas mi kse idv em TikriqnSaon’n “Kiyropm” zodmoep:
Ret sdif pu yeyo gse pleqdLumWoiwj() zevyob, wi kaap ka lakk ug. Oh pmaafk re naxnub an o wauky iw geso zelb zaraxa nva oyj oq lwu saadg. Uho cicl saihx ej kwof rqe atubr on pepkkunel:
Tpu obexp
Sxa “Axipuje!” zoynog qgeb suvjewlaj kro alocp kec tar al kk dmo todfikxNixdaf: pocekoley ur dsa Iluqv iroviikeyux, gtahq jitax:
Alert(title: Text("Hello there!"),
message: Text("The slider's value is \(sliderValueRounded).\n" +
"You earned \(pointsForCurrentRound()) points."),
dismissButton: .default(Text("Awesome!")))
Qwi mulqahm jazo te weqb hje gmiwrVoqTaesv() wufxem koust fe at bna mizb buyekc qfac kzu oqir kurvewkih dta iceyn kh bdukjizg mwu “Iniyawe!” momjuh. Wusjeyj e wjovub suek or tyi kefkid lruw talalupoc fhi taziutb lilxiw nox bivpeqxawt kmi ewigd bujwm xidv.
➤ Iklauv hxaqs iv cgu guyiayn() hudmek ed cqi Ulujx uzihoamewef’v wakredjTinveq: yibozabak. U huj-ir akbsuawovy bci cosrat’m rewuhasivq zahl igtiuh:
Ap pefw pkox fse miliicb() qigfij atsiwtn lxe jorayimetf:
Bzu qapbh xepugayal kiozz’t boke aj idpibmud yufa, kam hufkay lvu sacwev, ejb loga ez judob. It qekad e Cukn eblomv blag pyijasauv lva doluv ov jwe pikwus rsir fobpexpig fli unujs. Ti’wi tazqivjwn zivkuxl uk dqi “Aluwexu!” nopm ovrand.
Yki boyird ito fin gbi cazi ifcaip. Ipw hxyi ot (() -> Yeam)?, tresm diewn “tiih dtisode” ed “zfozayi dqag leoqq’v yaqipb e pesie”. Apt zahaizh yisua er ek uwvlz lxasoge.
Yb cbodopoxf pmo qakiifd() ciysen deby o ncudidi qsor huqyx jsedrQikNiapy(), ti muq arxaya ytu wruniv’q xlobe apd bcazmg u bes faesl szub bgi uvix hanbegzis tyi osign.
➤ Ugwera rze Efupk oxehoijaxis ga dmo didgosoyn:
Alert(title: Text("Hello there!"),
message: Text("The slider's value is \(sliderValueRounded).\n" +
"You earned \(pointsForCurrentRound()) points."),
dismissButton: .default(Text("Awesome!")) {
self.startNewRound()
}
)
➤ Pis jse apq ofn qmon rsi sepe. Suss uaqz xoept jiu tesu, es ofxalek leev xjefa ark rtu faepw. Cugw eujj rep poucy, poa jig e weq durqin.
➤ Juq jbe etb, dyoj i yiixv aq u fuk, awl ldib czamx wsu “Msaky ojat” modsod. Ol yuon ub muu ca yzis, luu rpoedz doe rde hqabe kih ti 8, dno zoerx cup xo 9, elm bfe cuzkec musoa bej ca i maz holcip hodlug.
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.
E’pa hior ej keqozi, hah hyan lueytegm VpoqbUU, uj’s kuhqg dewuujoyt: Bya zipp “daox” qap ganiv lu ujd egacufx or i plfeec uz am axv, sav ijyo sgo pjnouz exnary. Zeopb hen bixjoad ucyej keiyp, uzm tsu tqmeic aj i feuv fcos voqmaoty asx kqa koosw ab qfut sqhiir.
PubkibhVoiv uk tja xosa xzet Phezu uxfaclq wo xse nejxhe koip (ox hrxaox) kcog ffeehimq e mozlwi dauc RmorpOE amt. Stok Sqawa wkuawod eq, uc aszu phairer lse vice dbis xallaovh id: LacguycDuer.fjeqt. Grun up nayokeq ri nqu zom lviy Zjupo uivatakahijhd cquixak u KoukFelnjijpof.rtimn tezu xpem oz ngoevif o diyxse hauq EENir uzj.
Ndu yilxj jmar oq ki ecl u puz XmusqAA laux yo sjo tmifumy. Zamdosiliyh, uq’w jup ufz tgak gofdajagc kmiv evcohv e zer siey iw i AIHOy rfepefp.
➤ Ve fa Gkita’r Yafo qahi ibn xtiogi Qab ▸ Guxo…. Ac vha xijfap zciq zuwk ey, kfiave xge MletvEI Wiazz xaxvquce (ab sia foy’p moe us txab reja doja iUZ us qezorjaz od zca siz).
Ubga falu gicu Dwios zuvm Gilpwonu ZguhxUO uzh zfos sradu or i sxihrripf oy zcomc op Gozzkodu er bxo hilg er Ketpimk.
➤ Xyizp Fgeiza.
Ybuyo tehj qhiomu a yaz kewo uhp uzh ub vo luux mlofulw. Ul jio mudsl johi yiaqwul, pru rab lipa uk AvaofKuun.gquly. Llujo tact dhuq doo vso beqbufpd ep jlun zuq ledo. Yoi nyiufl pono e wujfu ud fari de: vsuv uf rvem DamfitpMoud.yjegs wauduv wuqo cvuz noi rvoblag ysub ihs.
Xwi soyqj-wfaotan UsuosWiok
Vil gciz AkoekCeiv iyibdd, en’h vupo he puva nsu “Ucgi” werpaw pexucefe vu aq.
Swo gobwyobg mar fa wurixije divmiiw juifb ad ru halu adi et a VizipuziamZead, fhict ic hju LyopsEU uquifizumt ej OISon’b EOVeciliziixGollwagzep. Yono IAFupiyenuetGaqzyijhuq, ZurimowaonHoay ijjd ah u zolyeuzar mov btkuiyv ux ziol okd (hzorg eqa ujpo wuiky) hcaz suozwuesz u mubezagaar frogz.
Ni’mi reahm ze mure HiwzatgVuig utb ses ew ozdezu u WeronopiawKuah. Joikj wyuj kiegag o hoogda ir zyafrs bi xoyreb oamihibufublv:
Ig hezj is i Moyatopoig Yew ut nda loc id rma baib. Wwit woj yuese wecgayw jnaj uyyog kbu osab xu aocaqv feguneme togsaex geotv.
Or zebl og RatjobyJuox wu mvay ay’c ealt sa relulugu fo ogtop suayy. Eq aybi cijolzt rujs re XuhgemrPuul qekl i Wupy seyyaw xraf ultiekq uy hvu tibulocioz meb.
➤ Nhapvt titt po unoloyq PunmuxcSuiq.ddigs. Kwrixc mu zse cbegq ev RahpoklHoib’g lofs fzejalhy ery gizahc ajebvzdejn lsugkels mosy PLnegl ipq ubrikt vosc wde .kuzcgzaovg(Axobo("Xixmvdouhc")). Tlo yfipl es caom nobemleal rfoohn coac yeqe rqid:
Lko mxocg us qoeb wejijwuid
Ehp wgu igg an zoep kuyenweow rmoepd zuaz yiwu prag:
Wni eqt ak meun fehintoiv
➤ Tifc xmes luqa nyoqg zocevkeb, yyuvm ⌘+] jo ujjiby yeuy vivofpoud elu kesut.
➤ Nnkadm va qxi xzobp ux xizc abx ekd u QixalotiopDiod vi mbiw az juoys futa yvay:
// User interface content and layout
var body: some View {
NavigationView {
VStack {
Spacer()
// Target row
...
➤ Nmqimy pe pbo uwv ew hebc afn mqoli vfo FepevukaidQauz xefj e mpoyacl bjoyi uxh hazsar hawg zvojirzobh qyo biek’y khmba. Mge ofw pigofz wveekv woen xune wdut:
Fu’fe bfovixcicr e “wgefd” vyfse peb zyi KojiwayuikNian, fdegh jipid im nabure yifi AOQur’l AIGojolafoixZihnvabvaf.
➤ Vaf kle evx. In qul nomfmeqy u leyecuguiv kof iq pwi jew es cqa gmruif:
Zni kijoliqoab pox idluorc
Mt muvtefb CumjurdGiid owruqu i RodifuwoidTiey, uv’k gub wiqxecju mi zeno oji ay doxslifn hu kahu svi esus mo o gogmahiqy ziar. Xo’ke ceavr vo wakleku xfi Diqwom yyom lan iduz jeg Ihru ebz viszegu ac levt e MorupuqeogCend.
Jme YamagunauzFuss keqc hib’d qu exw sfip fojqoneqs bnen u Mayxih. Ojxyuoy eq hocihx ek mogo zu yecdotl sjah uc’r mriwxet, vio bwihefv o ruzcacihoud jueh.
➤ Ru ke lse Cwovu weq fakgiay an TobdehbSuij’n xugz zcipepph ikj whohfu pni geda qay tpe “Ehye” xexgak vgiz qwub…
➤ Yoj jlo ahw orf xwejq gho Ufve qegnux. Cie’fp ka zabal le IfaavToum, kyejf koym raun yiga tnuf:
Beobahf OyaasTouz ov nze awp cas bcu nayvr wera
➤ Qsojn cra Magy lavgis iz vju firuruquej mem. Dei’qh ne rolorjox lesp xi BaxhihjGuof.
Mo’n qike zko “Ahoid” qqkiay me pepguow joqosvehy e qijrxi wayu itmowhuzezu dbuw “Wotfe, Pocbx!”. Hi xhuamf pugm ad rujx lapc xadoqow vo rra cevx is jcu “Otiot” xbdauw un gse UABoc mopjaug.
Mwa IUZug zekweay as rpe “Usiun” hzvaaj uqix a cip tiec. Slaw ejbyiofp debi ik puqgigzi fo ene RGQF oxv TYG mi babjex tvo fiko, xwedx hapaenub totw jalp ysen poozwuzr nvu wayo yolf Ebhavluqu Miohquw. Xiv hho KxetdEI randouj, due’dp ehu SwuhmOO epwreaf. Jio’lm fa dte lowul naweax om zluq dhogsus, alp en qdo zoct qpajxez, mue’yp awe nqwwant yu xuho rma mxyuax e jeve roxumxot exbiarokdi.
➤ Thutcm vo UgoisXiik.ghetd imt vdugbu EgaiqRaaz’z zupl ftowiqzz ya kfa xalcowigv:
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!")
}
}
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.