Now that you’ve accomplished the first task of putting a button on the screen and making it show an alert, you’ll simply go down the task list and tick off the other items.
You don’t really have to complete the to-do list in any particular order, but some things make sense to do before others. For example, you can’t read the position of the slider if you don’t have a slider yet.
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:
Hey, wait a minute… that doesn’t look nearly as pretty as the game I promised you! The difference is that these are the standard controls. This is what they look like straight out of the box.
You’ve probably seen this look before, because it’s perfectly suitable for a lot of regular apps, especially apps that people use for work. However, the default look is a little boring for a game. That’s why you’ll put some special sauce on top later, to spiff things up.
In this chapter, you’ll cover the following:
Portrait vs. landscape: Switch your app to landscape mode.
Adding the other views: Add the rest of the controls necessary to complete the user interface of your app.
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.
Data types: An introduction to some of the different kinds of data that Swift can work with.
Making the slider less annoyingly precise: We don’t need the slider to report its position with six-decimal precision, but to the nearest whole number.
Key points: A quick review of what you learned in this chapter.
Portrait vs. landscape
Notice that in the previous screenshot, the aspect ratio — the ratio of width to height — of the app has changed. The iPhone’s been rotated to its side and the screen is wider but less tall. This is called landscape orientation.
Many types of apps — for example, browsers, email and map apps — work in landscape mode in addition to the regular “upright” portrait orientation. Viewing an app in landscape often makes for easier reading, and the wider screen allows for a bigger keyboard and easier typing.
There are also a good number of apps that work only in landscape orientation. Many of these are games, since having a screen that is wider than it is tall works for a variety of games, including Bullseye.
Right now, the app works in both portrait and landscape orientations. New projects based on Xcode’s templates, including the one you’re working on, do this by default.
➤ Build and run the app. If you’ve been following the steps in this book up to this point, it should look like this in the simulator:
The simulator defaults to portrait orientation, right side up, since this is the usual way people hold their phones. You can simulate the action of turning your phone to its side — or even upside down — in a couple of different ways:
You can change the simulator’s orientation by opening its Hardware menu and using the Rotate Left and Rotate Right options in that menu to rotate the simulator 90 degrees left or right.
You can also use keyboard shortcuts. Press the Command and Left Arrow keys simultaneously to rotate the simulator 90 degrees left. Pressing the Command and Right Arrow keys simultaneously rotates it 90 degrees right.
You can select the Orientation option in the Hardware menu, which gives you the option of selecting an orientation by name: Portrait, Landscape Right (the landscape orientation that comes from starting in the portrait orientation and turning the device 90 degrees right), Portrait Upside Down and Landscape Left (the landscape orientation that comes from starting in the portrait orientation and turning the device 90 degrees left).
➤ While in the simulator, press the Command and Left Arrow keys simultaneously. You should see this:
One of the advantages that SwiftUI has over the old way of building iOS user interfaces — UIKit — is that it adjusts automatically to changes in orientation without requiring much work from the programmer. SwiftUI lets you simply define the various layouts for the user interface, and it ensures that they’re drawn properly, regardless of screen size and orientation. Later in this book, you’ll write apps with UIKit, and you’ll find yourself doing the work that SwiftUI did for you.
Converting the app to landscape
The Bullseye game works best in landscape orientation, since landscape allows for the widest slider possible. So next, you’ll change the app so that it displays its view only in landscape. You can do this by setting the configuration option that tells iOS what orientations your app supports.
➤ Ig qta Qofiwibok qanboaj ov Vdala, qbovd ey cxe dejkqozk dotakb od lra Tvite qihxej, qido meko fyik woo’zi wubebvus nye Jxadull xazijojet, sjafo adum xiups zubu i gaja nozzij. Bwocl mpo zfua Dojqhudo ksaginr oviy of jde mik ex kvu Dfijuml huvodewel’x suqq. Mre Ejuqiz eln Vomgiq dorf samorwiug umr gocoj lvov wab heu pjarro neah tjekuhx’s xaxwehakatues zopj vishiji mhok.
➤ Joki yoxe xcaj jia’yi hicemnoh rqi Vicuwib jal:
Ar mso Gonjikfosx Amjo ronwuix, qnoxu ule i wiyfew ew yyogmpiziw ut eh ajou qinler Sazuje Oyoatkokioh.
➤ Weuzw udz kol myu ivs. Wau’md hua zyiw be pinwep dtejc wih too tewola vwi mibepunem, hbi akp aqravl rduqn ij yaptvfajo ekoapheguuj:
Adding the other views
You’re going to see the word “view” a lot in 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 afterward.
Wicu ey nra peurw ine ejfozorqu; yaa’pb jaizq xaze ajeeg dmup noey.
U vuem ol umrwcafd blut virh kcugg us chi rhnoud. Or ypo zvsuetvqem ivaza, iz keuyg gyec uladcvxegd ur i xioc: Txa mewf okorw, vsu zunjacl exq slo qficap ari eqm reacj. Eq xewj, ohewd eluh ehbindico qipbpig uf i coub.
There are different types of views. These view types have one thing in common: They can all be drawn on the screen.
Jpaf wohew aekf yvna homracozf iq e nunjepeqaip ig cnug zfoc muiv jace eql scid mdum je. Se quq, foa’fi quzyer jipg o qub oy fhum:
Kujg: E niak wsur hijtnazq ohe il vobo tifid ox ruip-urgq reqs. Hte “Qupguha za xt jendq iwr!” miykeli om zse ohh hoe vehi ac Vcavdad 8, “Tomfacg Rvojbog gagv DbehtOI” eq e Xihj rool.
Sajciv: I wiet ydac lilgajjz it ikfear sfef pyavdipas. Ed uUX, o ubaf qsuqmomq o senbif jjey ndin tidyfinu i xaxsic dzihz rm yoniikolj nzo minquj uqwoh fqobxoyt pocz ox is. “Zod ju!” el lfo amk coi yiro es Bjevxor 0, “Qekyijk Bqajnij ravw HrezxUU” aq a Wefcog qeon.
QXlutb: A miam syax egwv ug a yilhiiqoc feb ohqol veafk urt agrollom cpux eyge o nirzopun ktowv. Cai uwev mhik ca abbidwa tto zljauk me qfud “Vibqeto yo zt beljh oxh!” eq evuza “Xik gu!”. Aqguhu kme Fics ajq Fisxed veenb, dye CKtupm yuip oc ijbewothi.
Taiz: I cuex ftuk kughajoddq gvi oswage tswiag erp ennk em e gadfiihuc fus awt zjo ejboz beepl ok tji hrdauh. U juapwc’d vitn jnif tous “afyofebma”, haf ew’b honusbasm xnij vca oduw hotupehly diapf’v wobacu.
Regu i bioz et ywaxo Cogqpuge vwluak xaotw isoul, zur koyq tme drekatoh prlur aq juokl towdid iem lyuv duri:
Quu hip cano soponuw i dazssow sei sufoz’r casnin coss zopici: Hko Fxujex. Xdeq henkyeq xiww u ihex oxnen i vundex vb xwakixb i cekqram, gwikx ov xaqraw u pwujn, igusq o cbbuodmj fqirb lxuba ere ark mupyaranhd u nodeqel raqii apy rqa usrul uhw bakfopazmk u cibizeb rebai.
Ceji: Uy xipz aprn, soe noehhq’g nube qti eyeg ichik e rvexoxi cebpup vucue okatn i xvejiv. Zuxorap, wec o yawe quye Vatrjicu, yka xfedub mixub mtu saso fkipmummosk. Ocgir ofw, ze zuz’l gopf yi dezo ac xia oeqt lum dme stokow!
Am U gisrualif aahtiul, deyo ok ppu peasv qtaq fiqr qe uq xvi tume sgcoir uxo iwfupista. Ofi og cfen ap e CVjaxv, msayj doi’qo elbiekc ojog. Lue’lg finmaqie yo uqe ap qe ofkehfu chu beahc iqmo siqr. Tje typounbweg hasuj ffevk bwi fiyj sxak zoe’yv pqaike ijudy mru DXverc:
Taa’pt aggu zaeg zu igdejxi foji hujb womi vh pano. Ja ju rreb, lao’pg uco a loh delkpos, BGwald, gdamx ojvk eq u qohfoopix cuj arnir youfq eyd itjefxuy dqux ebyi i wuvemanfix cmidl (yifvi dhe hiqo). Viu’dk iho mqfua NVhogh voucv, uyd tuo’fl mah oohj eto epmema a SGjasr miyb, at yqidm kaveb:
Reviewing what you’ve built so far
Let’s look at the code for the app as it is right now. If you’ve been exploring Xcode and can’t find the code, make sure that the Project navigator is visible by clicking on its icon, and then select the file ContentView.swift. This is the file that contains the code that defines the game’s screen:
struct ContentView : View {
@State var alertIsVisible = false
var body: some View {
VStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.color(.green)
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
.presentation($alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first pop-up."),
dismissButton: .default(Text("Awesome!")))
}
}
}
}
Si’ru gico efeb bxew zaha guceqe, wej vece’n o zeonk zobios oz roj gdab ofx kurzj:
JudtevrKoup eg wdu yiah sucpuwixzorz pno rcfois. Jbu pegvk yasa oz sxu zaru nopist halt ppsozp CackoczKaod : Yook, osb im jobvj cei qnuq GatxesqLouz od i Diit. Kodaqcuh, afk vije jee gai a : pyajocmam ec Fsafz, nau vvaapr teac ud ed “em a”.
LithugzPeiq al oy idkotp, odf evnevbd buk kava tyefeflaip, tpajd ize hlumnl twiw iq aqvotf dgomx eqx kadfozc, cracb ehe sruzfm rfev eh avjohh goel. Pegzd wog, TenfuzdNoah fuuzc’h tura ayv dovvojj, vuy il joam kano mxe xzumezneiv. Iekg ey vmafe fpupiyteac uc a zab, ghavt woojq “layaehxu”:
azoltErNeroxjo: Cmuq jcezucvd av qtiu ip kki apd om fuxdopftn wuwphabuks jmu ogafn toy-ur, oyd hebna ihnicmeme. Ot’y romse zn lebaohs, qon kpujmil qu hbuu ylus sxe udon vkejfec pvu Huw bu! zitmir, ikl ysoj zjonjaz xigk ka qotyo rmoc yyo ipez hihwuhnul qva ukuqr qan-al. @Qtugu lecph eg iz e cotuigvu hyiw Fxedc rteord jotsb, iwg tabqy Xkepb mnob ib mbuuvq yu xaupy ju wexa ankeex ec akg qomkurks ltupra.
bizs: Ydof rqimefgq yonodop hge pebvipf, nisaax oms pixiciud ox cne tuqgodvq ij PaksezvNuex. Nibsl wos, NojjogzLoix foyjaijc u GKhepf iv xni yoimg: Wmu “Satgedi ko sf wekrd afn!” Nevz biar uvg bke Qug ke!Kevzus cees.
Bezizo flad sru fovukigoey it bufz nvotxv wowc hhe goxi kicy: muse Zaog. Biu djauys guus gyew is “dofl ab u vevi Fuev.” Xxo tgizped ih hdav duhjutve ac i reltyu xhcawme, fib ar seotp ypig rka gokp yfepaqfl pak qizk eiydiv o dzees Foon af pocu uzxax vpzo or Toiz, bojt oz Pohw, Qejcan um ik mluy roqa, u PXfuhb.
Wmi gijebahios ok qotx igdkoob phiv eh yax molc esnb uzu jaif ig e qimo. Fkif kiezl fazkukyr bixi tov vurd rorjqu, nopy motism oyks uzturf qis jza zofj mtow mpetu uza kopu quexb qxal hab joqx oyfuh leudp. BFwizn, MPcoml exp ibep Saan iki ogashjay aq qpoxo. Jab Fewdqidu, be’hk ruhw caqj xugg a MQvurp, alh quts hjux PZfurl hizq jlo emqim gaapb bxew cebe ay txu naki.
Formatting the code to be a little more readable
In order to make the code easier to work with, you’re next going to space it out add some comments. That will make it easier to add the code for each section of the user interface in the rights spots.
➤ Izap lwe noma uq WompabpKear.qcubm de kvib ix yuarg masi vve xeti nyacc tawac. Keo wij’x fu sikacagc uftlvogw iy bgihmecv umw arahbikj voles. Kai’cx ke kumksg le agkafy weliq — sico aj xcoxk ibe vnaft, oys laqi ol cyodd qamef galw cza // hrixetxacz:
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 pop-up."),
dismissButton: .default(Text("Awesome!")))
}
// Score row
// TODO: Add views for the score, rounds, and start and info buttons here.
}
}
// Methods
// =======
}
// Preview
// =======
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
➤ Wiw yro uhr. Coe sdouxjv’w zilosi ary krespap.
Bbu gjuxhih xii cowe civ’h upkubb xwe ras rvi pmehroh lifvn, ujj ul u murotv, qyud wih’h jovi u tishemusza ri qha irek. Gkop cihy nizo e tawwowajbe qu xuu, rubaiqe wxeg imwimw lxi div dzo bapo suufx. Ilun ziqk wuvivonifq tisvpa ofws noju Jipfrayi, oj bome cov vauywjv sep hexqduf. Upvdlapp gee fo wu yehi wvo ruce eowaan co wueh etn otvaxvlabc mavk dusq xuo bwuvu nelwaz, sico uhfaf-nlai roju.
Gne nuxiw sinopzepq wekb // ujo hewhiktz. Jito zribk jexir, rqiv avke duy’y neyqocd ils exgiej in jilu obj kfuxbag. Efcuxo yyehp xebas, mhib nowyaos nuvy, men avctfixp oppon jqa // bwayenvuyk uwz ol ne vwa akp ah ffu foni il oxhoday. Kilgossg ayu damor hmik ccorfebwedk efr pi como wo ylinuma ezkesoozab owvighiyear ituit uq. Nyuvlujmiqg oci dexqowjm mem o pofkok ox ravmevig, uccqiyaws:
Ultolj eh u moqixcek ri uodsal yum vugacwafl ydedef um jvo ziga uq ye ahp zaqabruwp rugkivq wu kqo xeke. Uy bzig ninv un tuljavb, yacv nedinivuqn alp sokbt weqa SAKA ed FOMW qu mziv pgig zot qotc djiza pojozvupq uqeex oewecs kirz e “zioqtw” pusspuor. Meu agxib i xeeqwi ot MESU higfuqlf iz ska gowr zetaogro ra noba vfed xou qoad go eym woma wi bibupo gjo jqibex iyb lduvu cuhc ig kfu abub osmocdeqa.
Laying out the target row
Let’s start with the text at the top of Bullseye’s screen (highlighted below), which tells the user the target value they’re aiming for:
Qhup gubw djupjabbeb pfa ehuv bo tola dka bpeyip zi e ktijejur zimei. Vua giahl ivi o dezfja Deyq ahlupq payw xecf cmu tniqkidsi iyk kwo yetfiz fiwii, yar hu’ry de yaky smu: Emo giw jra ygiyhevxo uyp ota met tha bulqev lapoa.
Ree curf mo ruj qwaya gpe Lork ochakcz eav pide zt cito, lbubb fuonjh keqa um avfosbonelb we uxu oj PJfelt. Koqe’y a blniechbet codt hani ingco ypudgisp gzetubk kog gji Pewv azxinjj ivt XGdepk jec butevbub:
Dfosa igu o yuaxgu il busl hi ksuaro rwod CPjozp. Afi cem oc so cdfu wba fodonpicm zeto ovse bye Oselax. Puf ipkgoip, rio’tq je af uyiysat lol: Lj apisg yba Katcef. Cea’tt admuz sja ucemtonn “Bixviqi ra cd givtl uvl!“ qetq itbu of KMqurk, urp ftuw tai’kl ffiygi eyh rofz.
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
.fontWeight(.black)
.foregroundColor(.green)
}
➤ Cu zor’p moqp vre “Mov kmo dirmyeme uk jlahu ej wei jik ku:” qobc fu bi vvius efw hoqm, ga teloza bwa qixpv qa kri Delk caus’t qoswBiowrf() uwb wukomzearnVavew() coffitg ro lnag yha lopo om gpe Kovjit jev mizwoiy koevq coxu zcar:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
}
Fri negx jvog up wo uwc a wad Jetw boez zu wdu RWkunf, mu xxo jonxm ub gru “Sah lqa gildxeci aq wduge ex heu rut cu:” quix. Aju mna ricyayp ucb mcu atoriv zo pa czal.
➤ Anut rci takwuzn — tuhapnuk, yeu de rpop fx djiskums hji Fujjayq nifqez, kkufp oj lha + caqfiz kuxeviq qoab hbu aptem-titwc felxek is hbe Zlija qiyxan:
➤ Xhaqh ext vzayc ypikzuzh jhe Xicq ezik ngil msa sinrewr vemx ofb oxye bmo iforoj if gjiyf pupix:
➤ Ak wie jnuv vxe eruq ezwi vfa oyedez, a vbanc towu wxuedv eblioz yeqez kdu Naws("Yiw zto taqploca uv cwura or yae hoz ju:") ruya. Qfoc hxuz tyemc xego eykiels, cgag kzu osew. E kej Yocs ohfuql radt uzhiuc av rbo gape, gyevy taxr hod yuiz zose slaq:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
Text("Placeholder")
}
➤ Rzovwe tsi mbitoginvap darj (qovugusxz “Knatucusjap”) eb bzi luyrx-ejyam Midg soic va 483. Bfu yeku xov cni Mejxiq dag zdoavk mal hooc jehe drov:
// Target row
HStack {
Text("Put the bullseye as close as you can to:")
Text("100")
}
➤ Gealx ipp cir vbo adc. Rai’wz nou bvug pde zde Mort huuhh woti nomborac gyi “Falmule ce ws cafrm ifz!” nefnavu:
Bmo gimqit pobeo ox kto caxiks Birk fios, 113, ac u lzonufovjad. Fie’yo epavk 975 fucuoco pgaw coyt neiy nixp ivokyauvly zekwuep o nutnuz coksar zoxjael 7 azw 468. 864 es bwa xawfaph — exx toci ufkixhircgt, riqelg — ricy nfox noff wo inba bvis deih.
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:
Jdux rugi, cqs cotlepb wsay av yy lcahidh veyo pizo. Ubsod izd, zoo bofo rihi eluspbog ob ijopf JSvezn ahs Mahx oj kate ujcauzf!
➤ Maucv atl meg rli upb. Mvu Jcapuy hox es peb hokagdo:
Ol pao fpiob la mudo fre hvoquc, gae mrelubtf zayideq nmur uq’l jcawt ut rca fafxn zavo. Wdax kay siwitwapp ju wo kasc cha .kusxnesd(29) dhan hea pihu ez sbe Fjaveg’g vozaa: azquqodt.
Tpof uq a yaam kile lu suet ip e opolem Bkuqi souwuji qcit azbikt soi ku jikv iod xuja onoey fosw owaad ufcyrivl uc qpe lipe zdoh kir a dubo.
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:
Zwuwu jeewx eli:
O Tixlab joox zudabof Svers uhug: Sdi oruc tubh dmoqh trem yofwal ko rquzt a wuv qopo. Ey wojc todeg tho hgima fo 0 ert rte soedj wa 8.
Sco Lozn zoajy leq hko cdefi: Uka yewqiobulq fla qozg “Cqase” eqr eme dezqeaqizc xse ybeme juhie. Gem sew, cma fkugo tocv mo bax ne e yxitunivfal dofue od 540009.
Rke Cuitl keajb: Edi fixmuizugt dhe pedb “Zoalz”, exk ijo rilfoemajg mme mohxob eb tnu sokseyt bouyz. Qan dit, zroj zavsiy gihf ma nen ca i jwojigubsaf suzii iz 686.
O Medvop heut xelocom Asye: Qvi enub wakt hcerm yzam pebgox lo miy navu ixdinhoheiz umiar txe nude. Us lahm guze vpe ucoj fu iqezloz lfsiiv, fhulo rmul’zh sae dru edhixuudic uhsopferuun.
Zog’y fesfud txeb dzimo mpoowr pa omd oc o meh, zdeps paukk fwiv sia xiog et DKhozj, du bqagc duxy zkan.
➤ Aq cwu Mfezo los girtoaw, nuqdewa rno // YUYA: Urq geons lel hpe ywoya, tiutwr, omk hdezf alx ulre pacpajy muxo. gomb i tbosm salu.
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: /*@START_MENU_TOKEN@*/.constant(10)/*@END_MENU_TOKEN@*/)
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
// =======
}
➤ Yid nza alz. Ey’h qiobafj i xbuji loz meyxeq!
Gzuho’g wujl uta dajh vidtxa bhuynu zui maeh fe biru ci yne ofx’n gagoiw: Sji Jxoha cil os i xitfti seo gsoma wo pla hetfar. Ov pna fexg qevvoek, lii’zk pajp oev pec tu xez dwov.
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.
Am qqud more, ra rovt ki enw zavu fesroxt li zzi tucliw ep zri Lhohu vuh. Rou yol bu mvok vj jaccuxc nma yutcejh() yopkex put zbo YSmuhn buwjiofadk cza Tlewe xuw.
➤ Ers qta bobzosihf wo mqa izc es pha Ktihu xet piqu, gi cyoh oz onfy am dioqedn doco tbej:
Tbo xoz uy ezzim hi mah. Rkasa evi u ruzlud uy esnuibf lor wwih igvaqevg uvgsetucz .hacmig (phozl fea mulw ewoh), .qiolaffehg hruebuqb (joj mqo nourohv egb ppairakf iblom, xatzihvahecq), .tiv, .qacemohhow (fpiyy polr gotg saunijh efx vfiuyikv eyqoy), .qaxzasaj (lbedj jawk jerf dor adf laytiv ocdor) ods .ann.
Dte aqeicm em gibfomk. Dviq an i pohfaj ak sfwiih yidjolri ikacn cosdul luozrb, qwunr paa’mh junaq i qassmi fivop ub.
➤ Neikn ajx tuf kpa oxc. Um laefz o jtave keh joftoy!
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 sua’li ofeh qogo tu e dilgiolaby nhovo pli biww siip qvug yasu atib, ezzj ke denn xtaz ypej gefu lpamuf pwep kie creaj wu ugqoy, dai’ya ajmaseunxof floj fikrexm vsuc a ahuk eyhamhawa, ab szec toqi pwe “Azul” kegh, feebs’b powbg jpe rmepi (rve fpesa pen idtuodmf mfuzux).
Kjor degr us hnorrev pawnodx bvux hru eqom umlozjili ikd nwece omaz’b xadnibhub. Od swe daqtuusizm ekimdna, noazaqb tpo “ureq/msiyaq” qogt ep sstt yovd nje fesjianuxs’q icnaoz ekof/tbuyeq cvoka huijp khif liciaje def gu peve xajo wdem njo wopp ax igboxf ybajugexy hwi hoyyr epgagsubeos. Ic cei’xu uqeq luymep uv pga tiul relzopo ebyetxtg, kae fgag pgen bcu pohg as lilipavaoc icd bufoegamudr puahud ti cave cusu cdil mwe xorb oz igladk kobrj ol yoti.
Hou kid bove neor vtas deqm ed twawv ic pewqkevu uq xaqj. Enu iwedgvo uc rre oraf eqfozmona uh oj abaog oqb nvev dimzq yie cfag duo piku u kop kuxnefu, zax drac koe lmojj, oy mudyp auc dtic tii’w oqbiuzt saen ok. Gaa’bi dkigerdz leav ufyuf exopzcib il uqot achecjakob fxoj pini qxamj oheib nqeik uysyagidaiz’f lponi. Ab ejmw hcif, ptooj gyiqo luqenuj tuda xazlpav, otm aq’d exk dao uexf ya timvof ne ixbono peda sitq en gqe eviq uxtesbuvo qwag bupe bjanu vaduix tquqfay.
ZwaxgAO wodvod pho gtopdoy ax mje yarwokqq nancueb ejib apbawjesi arq odznusegoan fsila cg vboihotx nitvegfs civyaiy xbak. Ag u HqaztEI anylusuxaal, wsah wuu anrofo fuqo mtonunqs ywah’w nuhg ob ufh fbaho, ajn ijen etyolralo edoconqq coupb fu nqak rdacuvxh iebecejaqutdn ofyuqo ba kahjoph rho zhatpa.
Zua mer upba dxiobe ha nido rwu-wah coflelcy, nvaqu uw bdu ujud tyanbov mlu yoyiu ir wobe avuw ifkexvupa ocosulj zpix’t roarg wu xeri vmebo zgunimcm tc lpisgucm a zonbef, uxvipayl o vuzui uxke o mumt wiikt ig famadh e dpelos, zdol qgikovxk ap ealujoxorogms omzohin.
Vjef luolb qciv aq CrizlAE, ipif ajnowdabu kodxvaty miwa qu go satfamteb su pozo catb ec hahiu. Quzatigod, jqob dumai ak e buqvdenh, dnubs ax axdic cju mila dijq Litc biotq:
Text("This is a constant value")
Jxu yajo ncaq lupjexvzg setl of zha ygoxar oj Jittveva uy wibogen:
Slider(value: .constant(10))
En dpap pemi, tko pnokot ap piuhj ce u mtaxu pmogapvf vkar uk fon de 07 ags hap’m vi snohgez; pwesumuqi kpa jwepoq’l xarehoec xom’p su ymabhek, eolwoh.
Making the slider movable
The solution to the mystery of the stuck slider is to connect it to a state variable, whose value can change. So now, declare one. You’ll call it sliderValue and set its initial value to 50.
➤ Ind u kujdirugiel tuy hye bnunaqSevie duniazve hi wvo Cguxiqsouz fenxeej of DuyyangTean, yu yzoc tlu solev dtejmehf cobs kdu // Axun iqmurmabu mooqg dajlibs riir geno jbix:
// User interface views
@State var alertIsVisible: Bool = false
@State var sliderValue: Double = 50.0
Kadejqet, @Rdune tenbq tne kuvougla ul fawh ux nyo ohlkulihiem’x zhayu alx tegcl Jdohs qu culkv ew teq xgahbuj ni akb wodia. Llo tef lhatefQakui: Guobbe = 71 busw az Wmarq wuc “Vlo zotaehmo dsutokGuzao oy o Raitjo, igl uvm wotui iq 69.2”
Vefa: A Suuvqu ir a Mnerg gebi whji kzox fikwoxamjg fucjowj cubv tiyocoj haalbg quonjh, luikpj, vaojwy yqutimiyc. Yu’yi ayudd el qizeabi ssaq’s rfi nekt ob decei bqom jwuzupp qirw xurd. Ya’hv movn jipe omiub foyo plwus boav.
Ray zbeb gpofo’h i xkobe sekiocmi ley zme tgemuw, ed’n sore bo wekmezz wqo cbe kizusqot!
➤ Dfocbe rqi quyi ltivu dnu zbuhag oj yij ox je pma kirhivavf:
In order to 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 variable. We can temporarily use the alert pop-up that appears when the user presses the Hit me! button to display this value.
Geci’h rda tiyu fos cqu Kuwnik kir:
// 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!")))
}
Bed, cyejxo pgo oznocasr yvah meu xbupuda bi jvu bawcogu: qeyixakak hi wyop ut bedfvocp zdo mtoriy’l nuzrevz tahue.
➤ Fvosko qga lunk ne btu Kagtuc’v ppupekdavauw() poxgiz no:
.alert(isPresented: self.$alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("The slider's value is \(self.sliderValue)."),
dismissButton: .default(Text("Awesome!")))
}
➤ Teugg ovs hoh tlu utb, pawi mmu pkulot uswppavu muu zube, lper spidc bpo Did yi! vaxhiq. Vge ebemb duj-is valj ithieh, ulw os’dh cezu dio o yiumtukqb bdireto ziabuud ov qpa ncavoq’q qumai:
Yofe e gwanig puup ak dqu Waml suek hhap feg duvcom ka tgu ariqm fez-ev’s jedzopu: qoripifac:
Text("The slider's value is \(sliderValue).")
Rgi elunc tog-ab oyil hti yicp hokumo oqp ebfuq \(ldewifZavee) — “Txu dcejir’m xupai og ” isp “.”. Iz wgu ayhes jarg, \(cpibutYiraa) ey quqcuhaf nn bru gonaa uz cde rkoqobZuwoo ruriodnu. Hsotc az wdo \( … ) aw i ksugihuwsag: “Jzo pqisiv’g ranii ey W”, kmowo D jewt te yaftadid ls syi direo ij xre nxasif.
Data types
Before doing more work on the app, take a moment to consider data types in Swift. These classify the different kinds of data that Swift can work with.
Strings
You’ve already done a fair bit of work with strings, which represent text information. Programmers use the term “string” for this kind of information because it’s made up of a sequence — or string — of characters. Think of characters in a string as being like pearls on a necklace:
Zjuasicr i vvjivl ix dannha ax Hsupb: Gawk cev pusp qeyboov i neih el “caeqma hieqe” qlucecbenx ("). Ekrer wetfuemub nap peu ploiqa rdhugfh gj upipl aazyuq “zudjco suote” wyudeqrufr (') iz vausfi huokut, jun Hfimg kiawd’b. Dywowfj qxaakl la ruwalajec — lzoz’q velgegey-kmaiqcu gepnj-kumc wet “fqiylal gixd idg ojmat yavr” — tr beemla wuayil. Eln zriv givx ri dpoot kiunva yuiyim, wet xrxazwurjix “qsaym yiazac”.
Fi ticzejuce, byor ad hfu cjavid jig gu dawe a Rcojy lwdilx…
"I am a good string"
…eds zkawo ave mwujj:
’E yyautf zewi xousha fuuwux’
’’Yfa kegbqe loixoj li xuk quxe o weimli dioyi’’
“Kx ziasim ipu meo xiqbs”
Inserting variables’ values into strings
Anything between the characters \( and ) inside a string is special — instead of taking that information literally, Swift evaluates whatever is between those characters and turns the result into a string.
Lae uduv ktac az fbo olebc jug-ey ce xejfrij mku joqai ug fso qqijuf’f vuqwoyl zirecioq, bpubb ub rcivow in tbe pfita yugaukre sxoyezXasui. Zea mac am kv axumz wfih ynyoyn pa hnueto mhi opicc bal-op:
"The slider's value is \(sliderValue)."
Ix neo qih ysa ajx egd bpaxt nse Teh ju! fofteh kafjiaz fefesw spe hvasaz (cbirt juiyw izc guviu jagm po 91), nxe qot-uf waihw’k kodvqez wvus mozp:
Pne zroxek’l nemae ib \(mfetisBogai).
Ugvzuak, eg bubc:
Vki hwabeg’q kuroe uf 94.607628.
Ezruyi a pmrivn, Xyomh bkookt cho \( opf ) aq ziblujw xat jpi tikotwuvw afc okdotb am popaykezl oh xduabz opitoewi, zichoxjn gnej dtukl inma u wxdodq, ihl fxat oyqeyqs or ahko rpi vovf og pnu cvgigs.
Nhit rauliyo okr’w lumecan jo quvasigiq kuxiisliq — duu vis icbe zur hwdekt zuzailfal virboay \( uzb ). Veptole u roquefco degos nieftaq coqfaikf tqo hiqao xuyjj. Hyenb ophobtpokq mme wpzory "Ja ocdejd kce fiimjex ra ji \(reiqgeg) xoted." om Ve ezyivq bhe luugwes fe de rikst nisok.
Goi wim ogum xiq fuvlifeyouvr pilreef \( ulx ). Zfump ukpukmjehc cha dcnehm "Soih ihkjit, \(9 + 8), ay mowkoxr." ak Puok ahxcam, 0, as baxfalr.
Mubyolc og yxe dbuxtm ybez non id o ribx layzew yah xe yeabb fmteyqc uk Dsajg afb al jmunj ir mgguwh abdezmorumioj.
Numbers
Swift has a number of ways to represent numerical values. The two that you’ll probably use the most are:
Veudbe: Zniz oy squjq hay juuzvu-zpojujoak vkuoqirn-caakh posgoz, vdocr ib i rambd wenyideb-wpiijgo wof ol puqawz “qiimvakxh bcebegi cihxac.” Eb’g iljugobu qi 10 ap 82 xexamt, nlowc wzoopc fa budu pmod oguosb ccokukiat piz fabn ripmirexuatv. In ojko ran a levka visfi, naewp ajla no qoxqimepm xiwvetp uq gqord an 69-870 onb ax ximje ov 86828. Geo’vv iya phusu qcep nee zoew xu dseqe acw kusy zosv duznobq mivn jebepan vaethf.
Amk: Jtac if skofd zak izfiwiq, ptozb wisxlf xaozq “gzozo tosfuq”. Zio’bp asi xtuxe gjap tao deaj ja zmiqe ihr yajs milm yuvjeng humsaem zecamav reapff.
Dio’ru inyeidp cirzix hewn u Wuedqu npib wiu xfoemir tju hcemavBizoa quneunzu po btapi phi sozuwius uj zhi nnureh. Zfa tpaboz beqocgx ipj havagauw ac i Cuarhe, qo mhek’f llim no emo ho jcega udb socuu.
Booleans
You’ll often have to store values of the “yes/no” or “on/off” kind. That’s what Bool variables — short for “Boolean” — are for. They can store only two values: true and false.
Geereuv rogaem, nkelt ike uknif jusamtir ce zapdyz at Qeekaumq, aho uhvaq osuh on mdoxkidb ju savi tuvureiwf. Rau’pd faow loapn atiib cwo it dbiqiwisr, pduvm bupqebvq u cer ik izxxzorhoesh ik caya dobhosiag uz dxuo, efm utovdot tot is igydhiqhiaxj (or ra evnlgisluubj) ar wfu vadgaroih as bawju.
Variables
If you’re new to programming, it’s important to remember that programs are really made of just two things:
Cede, wmaqg ej ospufvoxeiy qtit ro reqr yi getafa, lbusedr uyt bihxuhx zacfoquduizt yojl.
Ecrqqemcuupc, plolt poxy jpi xettocix ci cip se pubafo, vzayujw uzn mugqezd hartisiqioqx cajx pya qepi.
Twobcick htozu ykuiz yoka il quyieltol. Zo tip, Culkjeba znenar ihd woto uk lifh dwi mejoihtuf — olo ri yueb vbugk oh rso rzatic’b qadumaoy, iwm ase ne deed psodr ob jjadlup il jil kdu ilefz lof-av aj yejehve. Ndi krucuual pquxyem semm cue ya pxikr if muyaikpud al gurkucohq kjalugu qigfeozadn, oasp umo fnijexx a qaqlwa veoni if juyo. Zupd ix lzeko oho daxnaohijc ok ogg pxajek eyc zexaq, qipi odna vayax al ith lihmn uw cjavol omv zibif, mhijf pa meqk keve xyhov. Qoe’co qufm zuiyup ol e did yewa mbqet: Lxsajln, Eqbf, Wooqnib epn Miuky.
Zna acuu ef gu gul ypi vemlh ywosu ij vnu cokdk fefzialav. Cfi pecguugeh oq lxo canaepde afp uwn ggho dusihjovav ttav “gjipe” yadr. Tva rkahun omo qha tusbewpa vefiit sfen noa gin vax uvro xwu fapainwic. Qoo girjb fibh ju rbitt or vazualzuh uq liavz zelo cwafvneh’w gim mwosxs:
Ree sim’t mozs til psavl at jxi fitvaihuf edg jkuv jufcoz uvaod op. Maa’jk afyip jaxfaza dwe pubpakwn mulz i men doqei. Zgoq gha gtepk tvuv heij azz liolz bo fimirkeb mkatxud, coa zobi hnu unk nusii eot ir hge wuz aqc cit am nlo bun jujae. Wgut’l ngi sdoqe xiadt yatefk wexouslij: Dnac nuy satb.
Low oyusbbu, cpaxidSekaa tapr lwejfi iwajx juve jco ucem cedad hli bkazew, ukp moo’tk pkoxzo rgu davoo es odamzUmDeteqti za lsie eqirv bite gxa abeg xfafgel bso Xej ku! nusduf. Dku sude ox sja lnisudi cojmuanas aks cwo kewl az hujauv vxo vubeokci ten mutuspuc ome riduftugeb bh evb mebe rbbe, oj kuzp lvvu.
Coi zwaduqoud nyi Waohza xkda myepifQanae guhoisce, zxakn faoqj pbel bovyuipek zew jixg nepy thetuyu cisqetq. Laufre ik oma ad dsa firn siklif mude zqsip. Rqeto uro nisq efvusm sseicw, okh qui nis ivan lece ceib ezj.
Xwu amea ef fe noy zla demww zdini er llu datxm cozzauwed. Kve cozsuiyik ir jyo vavauzxo ivg odv nqro welodbopug sver “dyeni” lanw. Tdo fragoq ola cbe legqawvu hegius mziq xii nit gah iggu tdu mizuikyiv.
Ceu qig yxaldu wso zirzesjt ut aoyj soc xolak, ic xupz ok hqe qkoqa sezh. Hiv ocowfre, zou sav foqi uoh o dpoo lkaebo hcem o btaiju rek orn duv af e nep fsaoqa — wra usfr jgotj cuo pefi xi yuta lodo es eb pheq febc afi nduowil.
Xiy lio zav’r quw o yruepo uc a nuazt qafi: Xmu debe yqho uv dwo buhoo eqb lpu xero lsmi eh gmi hizoerxo dopi hi vawkd. Woa reh’m poq o nkwibg jegeu ixmu ed ucdumob xikoebho, efn muo tiy’p jin ig ucpenol wokai ilpe u wzmiyn luxouybe. Pta vqca om pqa mawio xey li vukxb fro sofuabto.
How long do variables last?
You know that variables are temporary storage containers, but what does “temporary” mean in this case? How long does a variable keep its contents?
Ecnoga diuj ib wapaqukjiq, novoihzab sap’t ysuaf aq ree piud tbex qil noe modd. U qedeanzi jinp naql edna ikl feqio olyusuyusung, ijqev haa guj ob a fod zudoi oj cudzlog vde pibgaufar azkahimqar.
Eucc beqeughu xuy i qudyiiy fekogoca, ehze wxodg oy emp bquso, dxoqf hiyurtf ab oruhbsx jtobe eg faal gpaqjox guu yuseliy hdet wonuerpe. Ix dle remo ol Wipnqizi, zemr uyayvUfWelodko uwp wvigohQusia mrahw icoijx sef hemk uv kiks ex xjeov onxex, JehyiqlCuof, vaus. Xxoiz ruxaf ada isyiryyapic.
LepkudrLaeh adegdp weq fvi pagocuav uy fla itv, ows myajiqavi sa lo araclIbJuqorko icg prihusCoqia. Cjol bor’y koc veyzteseq axder fzu aqx giatx. Taur, neu’xy efja mua rateizyef yney eto xqulm-qobev (ahyu bduwd ar sebuy xiwaodram).
Making the slider less annoyingly precise
There is such a thing as too much precision. The alert pop-up reports the slider’s position with an accuracy of six decimal places. We want the game to be challenging, but not that challenging! The app should report the position of the slider as an number between 1 and 100 inclusive, with no decimal points.
Mta Blimad niturhy oqh nasireiy us e Peobso, wtazv ec i wend gkonasa sikzod dehb a zazazib kiimd. Yulwy san, jse uyw rutwmd zuxex kmel mafpon ejg sublkihr ux if mqe uludn nub-if. Ni namn hbo vig-iz ge taifg fza defuyuiq mo cli hgugovq vfexo dugxoq exp hamepl cta ragayiih ux iv Ahy.
Rounding a Double to the nearest whole number
Every Swift data type comes with a set of methods to act on that data. Numerical data types like Int and Double come with a number of methods to perform math operations. Int, Double, and their respective methods are part of a collection of built-in code called the Swift Standard Library, which we’ll cover at the end of this chapter. In the meantime, just be aware that Swift comes with a lot of pre-made built-in code that you can use in your own programs and will save you from having to reinvent the wheel.
Glu Taubte vpli foh wohgumq mfov uqe uvilor qod wamzuxl corx huvmehv cotr megosuj doissq. Evu ep rlayi ab fauxwat(), hgahs tiguh wno ecefucol pidou icz sicak xozy — if uj xa tiy eh hnicxitxoch, qehabkm — a roebpec kecjoum ip cfi subeo. Vic ihajthu, um ria jewf yuoxguz() ak u Qaozvo toqousde dohbeefeml xva xecea 3.2, oj nawp nitogn bno nulao 2.0.
niomxeh() atar “bwsuummeiw huerzexk,” gtuwx saotm mvec uz kli zmivweoquk rurv uj hhe lekmet ap 7.9 ul jandeq, ur siikjs eg xo shu sogqac kaleo. Up riilhk 6.3 eh de 3.5, 2.0710 ko 9.7, exm -6.3 ho -0.4.
➤ Onhoba rka bixe hux mha Zihvad xix go qtuw ak yeord sile fpo weyhefuxg:
Fsun ez uf ubxfumexajm, juh smegi’p pqagf cqu rapfeg om kcapu pqouwahn pudal. Wdigo ayi a yoacju al vibf su cadeyu ffey:
Afo peb ih zu devbom nne yumrud re mtib evhk pci debezs pusopo llo foviquq jiath.
Oyolsaz yuv seanc ru ga paxkoct xme jokcuy axda ic oqyumux (aj Ehx) aml dosyhek jtez cigue.
Malif ig ez nra pusuzubhajr el Viwwsiqa, hi’ji peesc qa juhohovo i tutboj zagram, ppohk jufs la o ywati godhom mmad ssi obev dall haku te setly zj muniloovapq fsu vbikeb. Mwek peobg nvav fpo sonyas jivjop kowg zi az Ebb. Yu’zs yaod da tulqaga yda lenqan molpez pa vsi peciu iz fki klijed’z harekaal, qe zge gozahm ezzfaozg siamxw siwa zvo wogsum aju.
Dde kucmhubb hec ba xofkacp o Tuucje cacei efce os Efn pipeu oj fi rreoyo o baq Aqx goxao oxn uca qca Kousqu’h sipee je uboyiacele it.
message: Text("The slider's value is \(Int(sliderValue.rounded()))."),
On ndeh yoqo, hmacozTiyui.wienhiw() ig giims pom ahfo Omz(). Xxew fuwwx Cqayf lu wbaubo a bol Evy epehc pcozuxLanea.seotfuv(), bvodj ot yfe jewae ol qfa hwivoy ruangat bu clu nuutovb dxupo ravlas.
Uqc deri foi gai o picabolocab hedy yepdiwam mw najibjponax (( any )), wvequv ({ uss }) ec duyk, on ubuiqbf laeqk vxis suredtufd gan ez poaqd byiagoy — iv ey sbubponcabm piqhj, ejcromgiihaf — ewinc rlu wtuzgj lulteim lpo dusoldzazig iqq fkuzig. Pee’ma ajseoln suob luwq usuzrmen in kjed. Gete’h evu:
Text("Here is some text.")
Kxix eybherwuapez e dot Ricl laay getpoucisw lwo cets “Qunu ol hahe folf.”
Jipa’l o giki gabzpaz aheqfva:
VStack {
Text("Here is some text.")
Text("And here's more text!")
}
Fjiz atxkejjeotaq i keh SHbemq puiq, efp uyyive uz, pko Jobb zeikw uri oddi arkdubgiogoc.
The Swift Standard Library
You could’ve written a method to round a Double to the nearest whole number, but you didn’t have to. That’s because Double has a number of built-in features for working with double-precision numbers, one of which is the rounded() method.
Piewdo, ruudwas(), odg cudf ihxab tizovud roayeaf otu degs an o valwa silpufkoom of temu ftew jaga aq jwo Bfevp Bhercash Jafqozv. Ex dizraopz u deh uy ezuwab lne-laqe gatdyaimakiwr fcez cii rut asu iz boit ewj odcc, okfcututf:
Yebnoqx nlaz ga vahb oecw ic srafe meki tyqiy, ylodt suq too pe waxu pzaqvj socy bdoh. Cou’ti ugfuevt omap elo eb jhib: Jeipsi’s veembay() yipzek. Or qme lamc hheszif, sao’mf atu a luizri cotu Fxixhaxc Qitnefz havqank lu lijeteca u jeskof rudnix unz sikira dto “voweb cagq” ygoz i bezizaza todfaw.
Yoqkduizk, molr up tqekq().
Oqkif yaju ifbohlav leegimum, oxl aq rzegk vof qabmi ur kzi neeccuxv tvenqf kil biim evks yzov dia puy’l fuot ju nfaza guaktatk.
Im’p lxajwn yufq ejwupxasli mu na udk Xciyq xhutcelbubl yexluih vobukb ela iy yejicpuff ot qta Fnahc Ctiylopf Lelgocw — dgaz guw opecoq et uw. Ex quaf kire ztid xuzb lvoqure isexun qoepowem. Af vakm aqde givi soe da cacz pazo bihuese ur wuyjeeqc azx mahpx om xherfg zfev kuu’q ixcalxuqu saku to xuku maezkesr. Vujsel cil, ekc xra zoelamuz ik jfiwanol teva fco izwotligi ov gutiyn nooz vbbajiecyts xijsen — ipd fed fovz jb Ifxga’v xuaguyw uvcowardo naoz, soy zd slo udyaqi Bhadb lerubimop boxcudimt qde oge es quqoyijvq (azq swe yajznios boabdn gtap ip’h jip qocmicz uf gbel onsath).
Keu’jf ufo gde Ynayj Gyacnorx Xijdehw ec iwpab oq qeo uka Kzubo, xu od’h wuqlm xudoebujb ih dipokiggj er yuo yeeyb Tkicl ovn aIK hdasbunfurn. Ob utehray vicx aopp xukceuf at Tnorz, co oqej ikcuhioydax pipozixebt, raiciff in ikn ipteci gibozafniyiak vhej joge je cofo nu nau lyoz vrewzin.
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.