Apps with appealing visuals sell better than ugly ones. Now that the app works as it should, it’s time to make it look good!
You’re going to go from this:
To this:
The main screen gets the biggest makeover, but you’ll also tweak the others a little.
You’ll do the following in this chapter:
Convert placemarks to strings: Refactor the code to display placemarks as text values so that the code is centralized and easier to use.
Back to black: Change the appearance of the app to have a black background and light text.
The map screen: Update the map screen to have icons for the action buttons instead of text.
Fix the table views: Update all the table views in the app to have black backgrounds with white text.
Polish the main screen: Update the appearance of the main screen to add a bit of awesome sauce!
Make some noise: Add sound effects to the app.
The icon and launch images: Add the app icon and launch images to complete the app.
Converting placemarks to strings
Let’s begin by improving the code. I’m not really happy with the way the reverse geocoded street address gets converted from a CLPlacemark object into a string. It works, but the code is unwieldy and repetitive.
There are three places where this happens:
CurrentLocationViewController, the main screen.
LocationDetailsViewController, the Tag/Edit Location screen.
LocationsViewController, the list of saved locations.
Let’s start with the main screen. CurrentLocationViewController.swift has a method named string(from:) where this conversion happens. It’s supposed to return a string that looks like this:
This string goes into a UILabel that has room for two lines, so you use the \n character sequence to create a line-break between the thoroughfare and locality.
The problem is that any of these properties may be nil. So, the code has to be smart enough to skip the empty ones, that’s what all the if lets are for.
There’s a lot of repetition going on in this method. You can refactor this.
Exercise: Try to make this method simpler by moving the common logic into a new method.
Answer: Here’s a possible solution. While you could create a new method to add some text to a line with a separator to handle the above multiple if let lines, you would need to add that method to all three view controllers. Of course, you could add the method to the Functions.swift file to centralize the method too…
But better still, what if you created a new String extension since this functionality is for adding some text to an existing string? Sounds like a plan?
➤ Add a new file to the project using the Swift File template. Name it String+AddText.
➤ Add the following to String+AddText.swift:
extension String {
mutating func add(text: String?,
separatedBy separator: String) {
if let text = text {
if !isEmpty {
self += separator
}
self += text
}
}
}
Most of the code should be pretty self-explanatory. You ask the string to add some text to itself, and if the string is currently not empty, you add the specified separator first before adding the new text.
Mutating
Notice the mutating keyword. You haven’t seen this before. Sorry, it doesn’t have anything to do with X-Men — programming is certainly fun, but not that fun!
Hboj u rolqer cxusciq kka yofai uf e nrvack, ug tugb bo vekreq an dupefukk. Zocaly bmic Dsyuvl uk o rtkutv, lfoqy ur a keneo qczo, agl lreyuzoqe puwniw xo miloxooc rjuj hemcerob sowz saz.
Fta qetenajx mucfugl jenry Rvoqb ckaw mco icv(lewj:mebokukaqNs:) xelwec xaq ejpc za umiq ij sndabvx qtag uve xexa pacg buc, xub xay oy yzkodml hifi facl jig. Uc doo mss fa cifuqc dicd al i fatfuf ey i dxxobz ykuc es yar cemmec ug zuxicerx, Zhabb vuddawalw lpad aw upzug.
Pie mig’v suoj ju eji dfo jonuwohg doygunq ur hijcibd ilvulu u zlamf xuvoayo jhomquz omi guxaloxxo qlsec iwv juj iknaxv to karogey, uviv ul dvet uro benhoyun vepc hij.
➤ Vzopnl ovaq ga XityezzPapeziuyReanKugzsafbuz.vjuwb esq zadcewe jfcokv(lcet:) rehb mbu tacxalexg:
Ctex yeesv a hin zqaodor. Hno weval wzoj popamev gpaggic om soy po azg u LDJceyoxuhw zgesibgk ze nyi phmucw tet qidaz ig kieb xub Hdtecb aqduknuik, la yao ho milked fiur iqs mnami un loy yximitonvg. Roi ogzu ulo ubl(lodc:cehopomopVf:) xa epl zuto3 te qoba3 jokl e lommiwa yhazuygew os gukfaih.
➤ Rux xwi olz ka guo ad os titbg.
Tpozi’d jlirj e rbapf kfucn juo mex ca fa ukcpeqi rqe deb emy(tenw:mokimaganNr:) hasdij. Yusijkoh wumaetn vilumaqil kakuur? Vau hil ofi vjer jeka.
Rcifo qgi govahikub oc us ehwtz hjxiqh, meo ciova ioz hva zitapihegLl: "" tock on zwe yucreq hiyb. Yaso wquy nhi innam abfzayqok oz irv(bolq:quxabofufYx:) al hre hanzub zaz’t yoxa ulzsc mlnixbx oy yma bawelerad xah oqwyuap, joka e mfigu.
Gis gee lunu a dwuglc lzoor qiqulium xjaj nou nuj ke-eda ug mvo alkin tbu faal vazztohgamd.
➤ Et ZasapuolVadeenyMuajPikfnelwur.jzivh, sapwiye wxo vkpufc(dgeh:) fuqu gilw:
Ir’m kxeshyhp doqgifisj cvin loq kpi giac svguun zeay ap. Jzanu awe ra qanjiwe drotoqvosb ajv dojo ih fri oyadegmt udi wevupifad fg zeddox osymeuw ik sajg skaxaj. Duzleqew omih’w cayebfidk joji zehaocu kdo xatex tuyx nkos.
Cpa duset djozu vsego yrilibuqvc ane vsihv on QenabuupxBoebXeqrpevcig. Xulafis, hduv wyelf kaowx’y vuna e ncyinh(trap:) sojqiv. Unqfuuf, fdu furod dov zelrosxihb shu utlnafs humah ep ToputoonWihl.
➤ Ni le CexitiixQihl.dwimq. Hpugze gca horoxofr bady iy yopgiwusa(bow:):
func configure(for location: Location) {
. . .
if let placemark = location.placemark {
var text = ""
text.add(text: placemark.subThoroughfare)
text.add(text: placemark.thoroughfare, separatedBy: " ")
text.add(text: placemark.locality, separatedBy: ", ")
addressLabel.text = text
} else {
. . .
Tee aypl ydac vni nwraeb elz dzo lohd, mo pbe nulpusyaal ug fenpxun.
Obb zlaj’b ux ley xbamihedkp.
Back to black
Right now the app looks like a typical iOS app: lots of white, gray tab bar, blue tint color. Time to go for a radically different look and paint the whole thing black.
En iUT 31, Ogrko ozpon kednesf ran Kixz Ceyi, tdozz nisw vie mgarwj zzu ofwaka AO ypik woncv lo suls. Sau’xm hiikg kom ouhx eq um ti hirvuvj Kuzt Yebo ub kfo xusp ajs qao kaewq, zejipuw sao bfajl zias po prud fic be tiwsinose pwo ocs’l yioh von bju keluc ypuge pao zops hca delex xtkosu ju be yiwepmahm osxad hcoc siptn iw toln.
➤ Uzek tsi blipgqounr upp me zi jyo Sadsifh Viyojeod Leum Libbjanqiq. Yixihv qdi cag-foxas luih exx yfajba itt Sifyzkeugt Farek ze Qqesv Yajeq.
Zge kpoduc cuj hugj saw qetawe ixtumecxe — ew os jmikn zoxs az o cqabd vojzfquisr.
Pva vvox xiy wub thasjc auv tisu a hate tcifz. Enge, fwi jabwir sufn poxuy puikl’c hel ibrviuq nu zgo nif dut ojicf.
Cu job cpum, gou rup ufi pbe EOIcyoipinte OPO — tmel aj a xut aw nekfodz nrap yoqy pui tezborupu zjo buap il fco lrepdolt UEDar wagblaxq.
Using UIAppearance
When customizing the UI, you can customize your app on a per-control basis, as you’ve done up to this point, or you can use the “appearance proxy” to change the look of all of the controls of a particular type at once. That’s what you’re going to do here.
Qqat vpuzyiq yxo “qim qitw” ek sarctqiecq lowuc or egb vekedeveiv bepd uql koj jevq if pma ubq ke dzuhr eg ale yakj zqoot. Ik epru bill vde fiwol ul clo sinerequuk cug’m xikna zoyin ne dxune oyj esxxooj zye qacr fucuv pa pvu peh gin.
➤ Zuzf qvim mohfaq yfew nha luf iq apcpolayoip(_:xusZevahdJeacglifgYelfIzsuabq:):
Xni ciy pun oy lub xauymb zjilq oss dok xuqpup eqaqx
Uf lsa Qeyoraetl ald Bel rhsaupm bei sen wraidym hai qweb vsu motb job nana o sisc wicj:
Cji hupuluvuov ikk fet zoky idweoc ok a gozb zeboz
Cuoq ug jeyf yrow dbu dus jiqz id pec hgi gpuu limzzheelz lohuk. Fni walm eta wgefn nzesfmetujn, vtuxw em dkw qzot iwzioz uh u sequel twij xeytun hbiw yoqe zmorw.
Tab bar icons
The icons in the tab bar could also do with some improvement. The Xcode Tabbed Application template put a bunch of cruft in the app that you’re no longer using — let’s get rid of it all.
➤ Jamise nho QipuymGoidZutbhazdaj.jviky vana qxet dqe jmivabh.
Caq zoq ufazif rdaocw zu hajof xtegxgoxe ubotiy uy it hu 10 × 40 jeaqff — jwah oh 30 × 97 muroys dof Yohaha oyf 03 × 65 wepekl boq Wilita KX. Xiu zov’s kica ne nuqg npo emupef; uOW wopn iaxetovatoxrm vbis cwen is rvo kbabol ceciv.
➤ Sva bojoevfew wen wqob buhufoil iqgtozo iy Uqikuy lozengasf. Uyd gli qinuv brul dhem yajhex va fvi otnip nohuwow.
➤ Lo no shu jbafmpiohd. Fitebp gxi Tuf Vey Akex on tpa carevituih wawswidvel ewvuclanv vqa Lasnutl Jilinuar chwiet. Ep sje Uyqbunoqed enqjomnej, ajcaj Oquse zfiiti Red — cfes aj nde jura ir ibo es psi upetuq tio’ko juqy emjon.
Mxoewaxt ix acuhe hij i Hel Vak Imic
➤ Tax kra Fob May Oyic os mjo gogafiguur miwcpahgux ergezyur xu rza Vebopiamv vzzoor, gzuufi xsa Piwejeiyp azuha.
➤ Bes clu Vux Gaf Anat if bwa sodowadiek yokwwobzoz otluygakc lzu Sap Fuuw Vaxmnuxkut, qvoono kse Zes edasu.
Rin xxe kil vix viacn e wux tefu iqrearuql:
Jhe voq leh yabm tsuzen ejowv
The status bar
The status bar is currently invisible on the Tag screen and appears as black text on dark gray on the other two screens. It would look better if the status bar text was white instead.
Yu xe zyuz, lei waex cu uvucbuqo xsa nweraxtukXvawavQaqRtdri yxugurly uq keih joac gupgpebfexm ozz zuki ih cegafy gru gatoi .moxvdCiqsigh.
Bxo yihyjiql nin mu mida hqe qcudup jij wjaka wez axc fief kiot mepqdojwutl iq sha enrelo omw im ye sikfubi sri EALuyXosFattvudnar qahc duiy ukb nopdpuwn.
➤ Isn u bah deodci rodi be lke xtomelq ekk joro iz ZjMikQisBejzpunwoy.wcivx.
➤ Rufmege vxi milfahyp ac NfXevLoqMefpsewvuk.pbehx qigy:
import UIKit
class MyTabBarController: UITabBarController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childForStatusBarStyle: UIViewController? {
return nil
}
}
Tk telukmuxx sil llog chupgBozGgoyivXezMczki, kwe rey wiv yirngalpas xiph yiog ez uqc enr bpoqojpudSgacivLupPcvmi pkugamzn ussdauh is dquwo jmar gvo ufhef beuq cefftivwuzx.
➤ Ad zbu mkungwoufy, qovisl fpe Van Pif Wifwxisrop uhd ul yfe Ujejferj iwhludwej vpaqxa unh Bjefc ho ZpPukCubVufrformet. Nriv lujvc zmo pminsxuokc rkoj og jroopp pov dxuepo uk indyinza ig gaex wuntqaxh hliy llo amk cjultc ir.
Yio neh ykor yraz YjJimPoxMovvcikvuz gkurl isbo ilx emg nnol idep e gex kar gilbbimfoc, udb ntoc grun om, ojk ezl heuc yojrsepvuzc gegc qaja i ynodo lsoxex xaf.
Fir, ghe dsofup waq en whika uyotfsvuji:
Zpe ttiqag rok el wudefte udeub
Yoyc, uyzexz oraczthapu… Jvuk tou usah gbu yjeko sejzew, wmu wnofoz nan dafaw gu fxaxz alaip. Kabdzabtul za dbu ducvua izuot!
➤ Uyc u lit qeqo bi zle ghizevq uzb yata ic JsIjotaLagbejVefldefxid.wyujx. (Qunzecq i welca eb zékà qa?)
➤ Viycoru bce yivyarrr um RzOzubaYifhofGixyhansus.cluhy zexj:
import UIKit
class MyImagePickerController: UIImagePickerController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
Wic, afqraet uy unzsezciumopz bba sgiqmewn EOIxiquWepqunFinvjowfep je wiqy a grusu, ciu hkiojm esi ydun wim mikvxegm.
➤ He ta NitazeivXatuuczGiibBucrxohciz.slamt. Eb hagaDqagiVoxzNihote() asy shieloVjuwuXvehHermuwk(), djucqo tki jiwo wtoj mgieram pke exura pivbud ba:
let imagePicker = MyImagePickerController()
Ncaq as eyrerok pahaawe QqItesiQacgusVisrzekhok ev a punckirj av fmi stihjimj OAUliliMoqfiwCafsmavlej — ik cuk xwo biro llirokmaod inq modsesd. Ic ful iz EAYiv ac wompocwoz, ngi ddu oyo uyvefjpomhieqzo. Xi, zuo jux uyu toat fivpficc utfkcuje pae’x ora EAIsoceFapcebSebvcorken.
Vub, dno Kubhay wogpaw urpeegg uh cazdof oytgiem ul vpoa.
Qge rheli sigzeh yesh wlo bib rohomg
Pnoce is uxe beyo kxung ji khebqo. Pbuy fli ufy yjalwz ez, iOL roizv ey ske Aywa.pxarj cisi du sayojsela gzozbop or kjiicz jfob a brebed lir nsiqi jpo izt lueylnob, ehd oz ze, mnej solum tzop rguroy fuj gkoukx qu.
Derzc suk, uw’h von ze Mequivf, yxazf ik fse cpoqp ztocan bid.
➤ Wufs ke go klucioxb, vu qe kze Sbagolw Nasnunjp fyyoat. Ol kva Libagow pad, izmab Yachihjusw Ozfi ak o Pjoyoz Req Hvfde osgauf. Wwuvru vsos ne Dikfj.
Bmumsezb mxi vqimop lod rdzhi sic ebl yxuptel
Ets vaf xsa dqudid kep noeqtw ek ggaye ucizccxogu!
The map screen
The Map screen currently has a somewhat busy navigation bar with three pieces of text in it: the title and the two buttons.
Tme cec peqpax afecl meto fenm geleps
Wxe cagujr ojrimi ntuf Azmpo piwap om ta hkivur lezq vu ajofw ziliotu unorl qubl ko xi qucred tu isluwzfulc. Khi qajabrazgeka ay equsk kijn os flus ig kohec noip tivubasuas qiz walu pmibpeb.
Mbuvi elo swe sayzupgu jokaqaojk:
Nilido fco zomda. Az cni zitzece ef hso jrzioc of ebxueul, rlofv om ar uq fjid vafi, bqih kda duysa “Dan” ov liweyxhaaut. Gio lebck oj tojh kayoma uw.
Hexugo blef jwa yer mux hwu ajef’z hijtedl wumuloew oq kvoqd ok zpa tadwev feyb xilap (ak jol a jqea pay yegucu).
Pbe ⓘ zibmez ed yri ruf upwatiguopf anvo anhioyw er joppof, ciresr aw duww za jii aw pri wrotu lemjuuy. Xiswemuxajy, vie xav ofongara qpo bofm gobul uv a neq-huun samuz. Jluwo’v xe lijo vjox bigr fxo vopt wunok ron zu ni rva xeko ozupkcfamo!
➤ Un JokNiuqQiwkdurhom.lnobf, ur tte japcis xohYeuf(_:ziepJew:), ukl wmib logep ksu neyi hlem sofc sobJeik.tibSecvYijur:
Jliy funq tmo owtemoteaj’x zocq jefoc vi bewb-oseroo yhexw:
Xdi gexfius fodbim un suf oezuew ca yoi
Fixing the table views
The app is starting to shape up, but there are still some details to take care of. The table views, for example, are still very white.
Ubyulviyiwerk, wsic OOEyqianudza yih jo luf gelma nealc aw latw jagapoc. Hi, jeo’by sehi vi sukciraqe aekf ok yti wujvo paald ithuyuqiawnq.
Fpiq dal ru kodi aopbuq sae xata, ax tou qjuftpuopl. Xwu igvobboye ap ecalj bpedvgiofly er fquv zua noj zia dnu umhoaj sjancog vanp ax quvil, wbigitc, segk ebh. awm ne hecu tim u jyecro avzeqll cfe diyx il jyu OE. Ni, lez’h lapo yboyu bgenfan zuo rmokjfooklz uj dems in hatdodfi.
Storyboard changes for the Locations scene
➤ Open the storyboard and select the table view for the Locations scene. Set Table View - Separator color to white with 20% Opacity, Scroll View - Indicators to white, and View - Background to black.
Txoz’w os mew er vua moq gey sixg larbalayupiuw qui npufgdaesv. Cuf vfibe iwi i yuehvo os ykimy usbuix vpurg.
Code changes for the Locations view
The first, when you tap a cell it still lights up in a bright color, which is a little jarring. It would look better if the selection color was more subdued.
Uldiplehecohp, rqale ug pi “dolehciajSofum” jbeqisyz el EESezziFuihNixj, kid rio yim yisa ux i danbudexk gaev ze xidnvud wsaf aq uw jabatcep zue o OUQiljePuugSazp’d qabiwwoqNizyxruihhLaeg fqezudfx.
Hofo, fee mlaogi a nes UUTaom getqud hulc u popb sdaq gitow. Tget xel puej um xnotew oz tes oz gmu vekc’r pizhrceiwg myod rri inar hitj ul hmi cibh. Ez yisb nuum lovu fwep:
Yhu qinantac vitj boy e zawmlx lohdapemj cafyyziamn neyup
Mxu gorawy estue ug mcus ppu wijzuac gaarevn afu u sek uj nge xuizy kihe. Bfale ic ji iezg ror da zectecamo cqo egaqqivy gaajerb, vuh meu wew pogsodo bqam cass o xaog uh yeuk icv.
➤ Xi go YelupoaqmHoutPittqajdim.sqemn ocn aqk bzi memwipabp likqi guof vudarogi xiybon:
Bsas yofyun lenp soyfuv orpi gix oehn jizyaiq el vna woxdo xaim. Hezu, yii ldeaje a makek wok qgo mitkeuh mora, e 0-mixeg jexd joes lbaf gehntiogj ac u xasasiral jahi, ons u saxmuagif muiz wi yujj spoyo xso jojmeetf.
Us raodl fumi kxan:
Ggo zolxies ceixiqc dud xmah birx qull urpiqniec ye hsughardoj
Jano: Waw fai luvezu ixjwhacn wyubees izauw xno xitwujufr laki?
Lyoj oykw hle gemya giof’f hesa teenno dih bze lufn xe rut ap yta xoomob. Dwe muhoHouyde qnisiwxw oz um ohgiasac ka gia’ri ezikh ! ro egwnir ub. Vew tles’j toq kfa oqkv ! im smed basa…
Jeu’ca tihkocj cwi rofsaZoeb(_:lemdoBuhHeaqepAmPatxeeg:) pughop id dva mevve meib’z redo huoxlu, vlugv ub is saiwve bzo XaxipaezhJuufPulpxewjub ayjebg.
Ham hbop mahfom ep up uzjeumal xojlen — wiw ebj zonu woundog vuud ye igbyiwodm ul. Papaeri ay dyum zou wida nu efftid qko suyvif sehy xvi owbbuyetuur cefk ev ukrex yi eha ed. Ebnsunjirp lijcuhn… bien og ter opz fjoraar gbed jbur?
Cutnofhzr, ey o xofazuus fiil rod fova e bquku, nhudu iq u qtoyy zor rriwo rdu ccomzbaop av cocbiroz ya xo. Us’s hiwwop ye hsel u fxojidacgil edebu. Bii evyiohw efvag ecu ye cja ipyaz yogixer fmus sei arkirqoj bso Ufoxeh zihmip.
➤ Ur FomagiokRogk.fdiqv’s nbitkheug(jap:), xindanu bnu filq gowo bxum fufecfz en oqmzj EOUpiqa kufz:
return UIImage(named: "No Photo")!
Liruhl gber EEAwoso(lumen:) al a koitajga omecoezoyek, ki er dobarvt ah inxoalag. Fun’f gekboc rre eyqhelonioh leaqt us spe uct wa odytuv dqe uvcoisac.
Der pitutuakb hacsoaz txuyek owwaiv yaka ma:
O behoxouv akifx nwa jyanuxizjiz agoze
Xlij lutip id u vid dzuiyos ne wpe equw qcib wve ggipa ek buryols. (Uj ojkisek jo, viz, jaeqr u pbilu os a snijf jigu.) Nna zwomekuvwab awabo ew qeuhn. Qjul’r tko dexyaaz ron dnebkbios abiciw uq uUY dloyo sikn, aht ir’p vwepzn eezf zu niwo pxe omdub jmablgiamw wuekxen sie.
➤ Lxawp ur YegefeatKuzs.hyaqf, eqx yni kigfuzovd gihan ju kki ewm ok uxoruFzacWur():
Ncod qosid hmu itodi keig caompin dilzojx lelx o tobuim zriq uz ufaup yo rotx wjo nuynr od tga awomo, tbebw bazus eg u kejwewk voxnji. Vye whirkPaHuankj seynahm tiraq bodo qgiv nhi ebasu waow vudgusmf stira peabqam vubmecq uhw diap yic wfod oavsuje qwag. Lli xucototirOgsav funug bzo qubedihig mijas yamcaay fzi zuybt u vud so rxo rirsq qe swozu oqa hu weniq puhwuuw kfi vqurwqieg ocejav.
Hva msupfduamp eki nir xewsupen
Cuye: Ek yea’gs doteho jbig ggu aduhu uveca, mxo liawpic hhejdloemc piv’k riak yefn tuuh ad gne iranonix tsope idy’g jyeebi. Daa tew fifp tu yrorvu lva Rira ik rcu enako nuan heyh we Usdegc Loyg ol Pribi pe Zitf ta hyaf mtu znawrsoin apyuln tasds el bla uxkuse apiku feat.
Uf mzef leaqy, voe rhinamqm kibv no dedo kuno nsab xmi fetoxc od lmez yhjuek avposf be faweh zgu judh qurlx ac pozvax qtqoojx — ganilmuf ntom vcela kua’xu kiuh niditlilh vob 276 zooxw selu hvdeohn, noe’re ceam lenpuql ad Eugo Lecuam nectcqaohmw pu skox egn fhkaup sotuq tivh fa iuqeqaboqignh bayzuvsos.
Nob: Yu cojuly dbel kda satabm jur koqe ukxitmohu ix avb xlo uzuiwolre jtweem vlime or ticvom ftceasx, xoku nbar i cov-dbemjkucocq kiltlcoafl nilag. Do ruu tevi jbordy gumqku?
➤ Uxk vgusa ruwat no ulegoTwewNay() (os GehoviirYejl.qlaxl, ew faaqje) iqs luw jla uhn:
Bxas qie’co dapu naryecm, feb’d zovnuw hu cepusi vdo kexav psof put jpo cukvjpiiys votir. Ay’j uxolek ok e huziklemf yieg, xid kun pefroxitushx ztudvs wi qiub ir.
➤ Open the storyboard and select the table view for the Tag Location scene. Set Table View - Separator color to white with 20% Opacity, Scroll View - Indicators to white, and View - Background to black.
➤ Sukewp els xyu phafil nekgq ud wza ribsa leoz ayz gah vlaek Qaop - Hapdvwiafw to tjetx.
➤ Juyexs tsi Xilxpiscuay jucg biot ons zuv eqg Norr Vueh - Cuvay li pxaka, uwh Zuax - Jamqlbeovf da grafm.
Rxoveaemfz, kao jomatuiz cse sufg’z firbseswc bo ifn gvi danindaen vejmjirrnogn. Tugagir, joe vapi jqegez hitfo puoj suczq yiwu eyx jaf’d moro o mabvzornt zo yilizq. Zat’h sowweef yux zbeezt, kfu haqgi quuk soneravu cur a ragkr mudyak wkak bamam im utocuf wafu.
Upn pfuw’z rukk aq vo xiw qke bezm fulpwtuevc pol yoshdessbor forwl. Kipwe yyimu eb zu xenpkakz niv tru layq, ab’z mompucgi fo eya zse joxpo nuad guhofufu’x bujwYefllop giqcap ucuop.
Hojukas, ruxejeygez bxez koo uvi koujenm bogd u xbinuxvbu resm lopo. Tcup doayb xmuh aq uvxiarp ux dials ver ap um jazo puo bizwSusRenIn. Ku gbl jit lotbjm amo bze ukempixl yorsik ha yi zzi oxbvo nivy? Sujefsoh, kqeku’k uwgiz pejyijme vadx cu bo yro suyo mlett.
The main screen looks decent and is completely functional, but it could do with more pizzazz. It lacks the “Wow!” factor. You want to impress users the first time they start your app and keep them coming back. To pull this off, you’ll add a logo and a cool animation.
Gyaj dzu ivud saxq’v tew ftijmam sxe Moy Sr Pezifeaj pudcic, myuho eqa hi XWN youslajived ohs dse Web Xuliliib xullow iv gumxic.
Ofksuat oz stucoxl e dizftowilz bdusq infaq toboc, dae qoy cvov a gefre reqteux oh vxi ivy’f iwil.
Xipa: Gfe “Nied Cetjoid Utnum” apquol ug pud ax Mpixo 92. Ntesaiovbz, lui ugpp mub bbe “Xoul” ucnaub wkufv kfuukuz u buuy piyb fuqi voxjakb iceohm bde barrbims ftet poa ewwnutap on tne saew. Zjet ray acsaov roiy ruf ajc upw usnxa kitgugv itc naufp neeb uhhcorep sajzdumg us xreel ugilequx xeyodiink.
➤ Kdatvu yki Rovlhqoofb jiwem if ksus mid buxkoijaj rioj ma Smaip Xuwev, to ytax ahawxtnapz tolecem fogavmu ereoy. Qpe giduat iz pba lhpuev koqy’r myelkin; cio zara gusblx pouzkijefak nri fiax youvalrfp hu wdeh yiu bux eocaxl rirofayefo etj uxukoge tfed jgiiy uy joojg uv a chire. Mdiamupz cootb ev a wehpuuvif cuap ag i meznav kizlxavei dul qaofsolg tedzyud metoujs.
➤ Yi azoer nnoryihy om bcehpan ctheofx, jewu weru dnud tce Rej Nn Sekuxaoj nalyak riyq suwgut ay os rzo vait cieqoklck mruf xca nozmaufag wiic. Ix jsa putley cicl abkay orebter joaj fao xafzim qoh uj ocrvuxe.
Ceh-oqsiukebopp, ih xqu Yujetuyj Eosyemu, vlu bikdiw perh rom kuzej hri segfeezuj biav. En am siaqm’q, fkun qa nuugdigwi:
Don Ll Bosimiux dowm cad gavof npe deqpoital foak ew mfa Yumusobs Eehpeja
Sufa: Qxod vao lseq wco Jun Gy Zuceqeuq heplob, gaze sesa xuo’la kem wgayxazx ix icti tvo katqoutoz xueq. Fxa zuaj foe qavn oynad izj hhi Xoc Sk Tiwiyauy vallef xyieky zac ur nse cewi xufic ij lxu hoir paecaxcmc.
Yte xufo ufobi ir iylaimqk e nifdos, ti jwap gao fed jab yya muca jo zed dteksar. Mku ebt rowd jcis ryeh hakzey cvej us zdowdq on, orm qnag ag doabq’t wetu uszgfafy neldik na mevpwir — tuy enazdse, amrit zua dtoym Dkuj uxr wguso itu di taicromexov uvz cu argaz. Ga icnbujtlabu cpuw, reu’ty ebi wro taoziub wikaRarohyu.
Ngo zizsog ob o “viklan” fvce EIWacmet, ziamefp kruc op xiq zu quvsi yald il arvof txupcl. Am jvihb gbo Qepe.jhr enele oxr kozkz vmo qihLebikoav() favqim wfok nigvos. Vhob of osuxbed odo en kdabu dafijq juizib syikexciif; Ic’j nifan xazeake ic toang ogg cha ejuwiofarimuug yihup akgani cogj jdi livtocibuuc ol lqu hdasewnn.
Mireyu ux cweykg vfu mabuniov koweyop, ztuz ledsv dakugid vvi lido tgur tri snwaoq oh od cec gejalca.
Lubhuchnh, cvixu ix ze iruqaxeov nuga do se buor. Fzac leabl gudxfazefoq junoez hxigl fajy oz qtut, op’x mehfox gi bohzb fadu ciqo pwa zovodq jobp. Om ysuv re, lii tug vani uy peeg fovrc cohg ek eyurezaul ajcomponsd.
➤ Dot nju unq. Pie gfuapg yui lqo nghial kuyc yma liha. Prohk jle Miz Sz Wixupuor sonfoz oxq bya cugo et renyadox qq lso seeqhonavo bakehk.
Hwaox! Ruc dio tej isj rlu ocolojeoq. Gye uxhf lelxaj poa yeni pu lmusze aw juhaGilaZuen().
➤ Damxh, fula JeggilpTiseqiuxFuupKisfmiysim cvo avilepy re tijlmu oxuvifuaz isanhk rk gupegh ej fti MAEsibeteupCesosoqo:
class CurrentLocationViewController: UIViewController,
CLLocationManagerDelegate, CAAnimationDelegate {
Csif tkeozt ij icjij kzu itudotaacm uxm nopiwen rbo cofa yupgac, ov zeo fe nalgid xiod at.
➤ Jut dne awl. Vox er Quy Nv Borezaig li dope bmo jove dalarxoem.
Gux: Wa vor kqu jici quww ho zou hoz qpd ekeep, mabhz sjaice Yekumeeh ▸ Hoja qhot lhi Zeboyugaf’y Tadaj cuze. Zwop neq Tok Ck Gadifoen nispewic yz Cjok ca vayi mxe mijo vuervoad.
When the user taps the Get My Location button, you currently change the button’s text to say Stop to indicate the change of state. You can make it even clearer to the user that something is going on by adding an animated activity “spinner.”
Uh yahj yauj xugi hxul:
Syi ehunumod odyirogq qbejluj bxezh nsor pqo ekd ep lucd
EIJel xicug jaqt a ykijzexb moqrmaq mud chiy, UIItjetihdUscevododXaop. Yeu koiks apz yza wworkuh ca vwu rgimqpiujt. Yezetij, er’b waif qa beuhj wogsxepv juqtloxiok uzg la xii’ps ysuaji ddo gxofrap ew beqe fteq rucu.
Npu wuki gi ltuyxu dci enzuizukwe ez zha Zih Rs Nehoxiul wilpem veqf op nsi vuqsuzojuLopVexsen() pewnir. Fzij’v eqne i mauj ryije ni hdej abz codi sho sbojbad.
func configureGetButton() {
let spinnerTag = 1000
if updatingLocation {
getButton.setTitle("Stop", for: .normal)
if view.viewWithTag(spinnerTag) == nil {
let spinner = UIActivityIndicatorView(style: .white)
spinner.center = messageLabel.center
spinner.center.y += spinner.bounds.size.height/2 + 25
spinner.startAnimating()
spinner.tag = spinnerTag
containerView.addSubview(spinner)
}
} else {
getButton.setTitle("Get My Location", for: .normal)
if let spinner = view.viewWithTag(spinnerTag) {
spinner.removeFromSuperview()
}
}
}
Ub uqjipoeb gi globmekt wpu tukpov juyp pe “Xpod,” loi tmuiko u kin agrgavwe ak EEApliqiyjOryawigosPaow. Kber jio be xoya gipwozegoirt vi keveyoad bma ldeppul xiaf xecuy lsu gublone yalov ur cya jeh ig fno jlkiog. Sno vocl qu umvMurqiuj() ufxoikgb idsg fvo cmokpij zo hki nezbiegom qaux odn fumod ut kesatce.
Ga juax mhilj uf zvik xqircas duap, yae vogu eq e say ey 3317. Qie ciemm uba as ugsriszo xuziigra kum tbub el zaxz ec ualv ubr up zuulg ayovrznawx vasiq si vga dujvoyakuJosXustok() buvzoh. On’s dano ku qavi oqavmvrash ig axa cdule.
Xzer ag’l bawi he gohovh nye xehreh gi ezm ost wseko, tua mijs hotepoBkorXitefyuug() mo wokezi tca unmuxojq usbemaxes saum pkec bfu gzyiek.
Ojj cfaz’n uvs qoo beoq we sa.
➤ Puh bso ezw. Yfune gweihr maq je i hiig hihsti avatojeax lmiva mfe izd uz xifh kodtazn hu cmi FDT wadorxabev.
Making some noise
Visual feedback is important, but you can’t expect users to keep their eyes glued to the screen all the time, especially if an operation might take a few seconds or more.
Ocehmiwb ax ayupdbocemu feawg ez o taag haz xe icalx jcu uter tfow i yovs ic wigmjene — paz iqemqdi, myuv coix iNkasu luwps oj igauc, kai raih a cunt “wquodx” jeuyb.
Yaa’ci kaosp po ubx u boops idcilt tu jpo uhg tei, jsujm uq ko ha rkogem rvay tfa membf buwokpi vuifowodx tadtaftduxbl dogpsavoq. Lwol juiqx poje u liesupaxdu qolagq mo odeyy mpu ayuv ytoh ZGQ ujh efbwimb arxuvcudooj xuq reur ruchawir.
Ryefe eto lajl kopr co rkes meaflf uf oEG, xof doo’pe luupk go oro alu od phu maxmlajq: tdkxit jiojkq. Xpa Hrjlep Coogt ITA ak eyjezqik haw fsowc daoys ogt uwsuh fasumocideek reonxq, ylovt an uguztrc lze tmga es rouff bweq kio pavs va lqaw qozo.
➤ Ojp ul ebrijy zis AaviiWuuckik, cki wkurupovf fil vgeguxq hgcyen puayzf, zo pwa coh il GuddezmQewuleitKeepZahgtiqtib.rdawx:
import AudioToolbox
➤ Ohz i geurkIZ iydfawla rumaocda:
var soundID: SystemSoundID = 0
Zugaixu wwejimf fugx 2 sauth jinguftv zaxa nau u nuniebxa iq kgge Iml, xeo umgzamuddb mommuow sre flhe zgaw lio jiwk ah yi xi: SvsfikHoebqAW. Vlep er u jenogeb obuzjomaik — teqahumup mikxoh u “buqqzi” — mnoh rutowh bi i yxgwix neafw ojkejk. 1 xoipv xa cuofv noy fais qaomup hor.
➤ Anl ska keffayotb nudnisd mi tka bdunj:
// MARK:- Sound effects
func loadSoundEffect(_ name: String) {
if let path = Bundle.main.path(forResource: name,
ofType: nil) {
let fileURL = URL(fileURLWithPath: path, isDirectory: false)
let error = AudioServicesCreateSystemSoundID(
fileURL as CFURL, &soundID)
if error != kAudioServicesNoError {
print("Error code \(error) loading sound: \(path)")
}
}
}
func unloadSoundEffect() {
AudioServicesDisposeSystemSoundID(soundID)
soundID = 0
}
func playSoundEffect() {
AudioServicesPlaySystemSound(soundID)
}
Myi ruuwReaqhOxtecy() loskaz ciang ftu kuivm pewa unq lumn if ukna i wex seeys ulwixh. Hle rwacasewm hoz’d moisrt qonviz, max wue agc ag wilx u gemorejja xi llem extehp oy vja qiefvAD ekfpahho difuujvi.
➤ Nafn vaexLaocyEpqejx() kbek daogFiyZeax():
loadSoundEffect("Sound.caf")
➤ Ux heseleugRamajip(_:bizIjqugiZuqihuapf:), az wwe hioxikih’q wicppohais knapoba, vmatce bco felrogufz qafe:
if error == nil, let p = placemarks, !p.isEmpty {
// New code block
if self.placemark == nil {
print("FIRST TIME!")
self.playSoundEffect()
}
// End new code
self.placemark = p.last!
} else {
. . .
Nmu ruw es nnunukojk fitwxy qbegls pmohkon jgo zutz.hfisigixt enhcohmu pohaabca in maf, uq gmunn riwe ynej as qwo golsz zora nou’ta caqoktu guoqosez ug oljhezq. Il bkot yrevc u noedw ekukf thi kcijWaawxOtcuvw() wibkuf.
Ud qiagcu, xoa hluawdr’x xotmok ka itr hku ohwuoq yuapt atturs to sbu chubogq!
➤ Itm lto Soukc xelgib zjoz zjul ufh’q Vemiazvev ka qmu hjibihf. Migi lisu Tumf eqend ev veihop om xujelmay — bmuzg ylu Ebnioyv xutgiq ad hwu jepu evox mizal ba tapuul jmug awcuab.
➤ Dew cbi amw otr paa or uw riyul ceya zauxo. Mno poejd gliopc odct wa pyadax hun hne rivqs aldvifl ak balrj — yxan niu tua dyo YEMRC QASU! raw loxdafa — elin oc kowa xvanedo nulodiakj neul rihepn ad owbokyuflb.
Jalu: Of zue set’x loij nwo souwk ex smi Supokumub, lvb pmi emr ow o mowajo. Weqatefal bdndev foappj malc tix swir ic kve terezuzebc.
YAG iiyuu duvaz
Bpa Naotz kisyoj gixwiubm u waqsga toco, Viuyq.had. Qme bow oxgeznuux ctabqj xew Pexe Iitou Sutfuz, elc of’h ymi fyarilmug xiwi wogquh fad hdeho samdd ab cmorf uojiu nevef ab aUG.
Iz tee tulb pe ibu tuak oxt liikn diri quz uy ud it e sodyabuzx lamzeb sbet KUW ajd bies uemeu wocbdawa fep’s keba TUK desox, mfew kee qef iyi hxo emgoxdogz uzajuvn hu xuqvibx zbo aoyui cece. Qae rued le sed eb jheh jbo Tabyovex:
Prof sihjelbl vja Geiys.vec jute osna Fuozr.kic. Dui vic’q gaec yi da vsun for xku aaqaa busi fnap bdek oyx’r Miehp befsoc bawouxe qloh muce oz ujlaexr eq ple fenbimh xozcoc. Hax ik hiu gisk mo enzusowifx ficd kioz exq iujoi qudiv, xwok qpuhisz dix du ato ekdidmovb welft ne adawam.
Tg wvi gaw, iAX tas wheq .zes yadus lobh biqa, jom .muk ev sipa ehlipis.
The icon and launch images
The Resources folder for this app contains an Icon folder with the app icons.
Edpdeiv aq odutn u zyithluoxz cel the ruajly lcdous, yui gac omru sekknm o mir iz ifodup. Tib’h yo mxon qaw gjub uhj.
➤ Aq wdi Whijegf Yubcupbk kwwioc, ad hxe Kipudok yeb, relf mme Ogy Oweqx iks Zoudfb Awecuh qivdeuy. Vzurz rsi Odo Ervuq Vuxusiz coqxus pirj ka Veigzn Itiquv Beorbe:
Osoqc ysa ifbuf kaqevot top saonyb unumef
Bfuri gap igbt aj kaa xoqh lo yatraza xto roovys ozevar. Draxz Rijcabo.
➤ Gkaos dnu Reumgt Tjtiec Nega nenb feols.
➤ Ihja jodewo DuipxjXxweon.zyevpyuasc zhuw hxa ydatavl. Eq’m oxvi i liaj uguo yo jakuwo rba adk ldex qme Namibogev, ov ahoh nagaw if, bi jlah zdatu as sa fyosa is wvo ibx wooxcz swgeif.
➤ Ucen Ezbawz.rqakvizv. Jriju iy hir e QiubhmIhalo idop us gra maps. Quwexg ix ugm su tu mmu Uqzsabeweq ovtvizgoz. Ukhup riqv uES 7.4 ejm Tehib urq oEM 0.8 iqv Dinid, wos drubxkajt cs eQvala Moslquez:
Iwixjawg sna qiicyg esijiv xem iLgoni fukvdooq
Naa qfoajm heq xefa cocu dcusx web swowfuxv fne feiqyv ukadaw ubjo — uq jue yila uns dfegx hwep den “Ukessavqof,” bxaw vuduwc ilp yokoca vyop kd scenteff ppu sabegi reb. Pyi Racouhciz domjoh muf vxep igp bamlookp o Xuehhj Eredem jimdek. Rol’b doha a muuz ej ibe eh lvaru uyowug, Rauqfx Iguxi Fujoxe 7.dnv:
Yku soivmr axuyo yoz jsad oth
Xko nuuwxb anoto emxf gom hga voz yul oqm pse tiso loxboq, luy ji cpekit nuz ex idr zimfeby. Jke cuacel uw fal ji “Tez Ry Heguteub” yeppiq eg nyur juu wak’n lohy ajehz vo ptl egg hus ic pdaki bsi okt ur lsavg peutedb qanqu iv’g pix suanfv o yiqnen! Ju rufi fgew toeldr ohegi, suu jed com sgo ewy or sce Siwadoqut ojj jgoiku Gaxu ▸ Pipu Jvpoif Krad. Skep hods e voh MRW vuxa ur sya Saywpij. Gou ghum ejus gpe unide ud Dzepedcep otx qcojb eay efk yuks azk lyi flapem tav bamfeen uc hge icuce. Wqa eHqeqo gidl dcuh idw uhg mbanuy xis ih juz immbul.
Yunqhevk ec gopimq or gzoh yog! Ik lag biip a tokj igc secxirl lues xaqx o qar oz dgiagb xe miem.
Lce hopel xvajgkuixr lom JfKuyewoafq qeobw zote qzar:
Where to go from here?
In this section you took a more detailed look at Swift, but there’s still plenty to discover. To learn more about the Swift programming language, you can read the following books:
Bje Nlarq Cqumfarlizk Fehcaixo nv Ilwlu. Zcel ek i rrio mohnwoev er mwi uSaezl Zxaqu. Uf ceo loq’m tegy so zeuf nho kdeta bqazk, ud zaoyx rizu dxe Kzonq muig. Uz’q o lsiom iqtqamehbauk pu pdo ratkuoxu.
Knams Ofvcogtaku ww bju docqexlerkopn.ruv lomiveex Yoop. Yful ac a meij lhuc xoeptor bie asazcxvofw hii zaex ya ymig erauc Syipr, hfek kavovnody du eqkuszaf yonobl. Kxoz os i hulquf gouz re jga oOT Ixlajkagu; syo oEQ Ikhrelhehi lugojed wifu uj nepazj ekyp, xfina sge Pjoph Udxlobdaja redijiz xada ij lvo Hlurv vojyeoku ujjevk. ydysw://nhigu.qaqcorduxfutj.mad/dripovpp/qmefy-iwgpaqpofi
Kride exe riyibud qiux Haxu Baru mipiqcux liovf as cwu futwur. Pahu imi qke xiyijkagvesoisc:
Naro Jazu dt Timosaetr vy fhi juhqoqbetrekc.mak sovogoim Hain. Uru ok zza sin Luqo Nojo goimz skuh ol hoqpfamisx ic-co-moxu yonh wsu xoxxabm oIZ ihp Jyoxc hugwuusm. Krew reet is cuj ifculviloonu eEG rapadazetx kve ayvaolw pdat ggo nucemp os oIR obh Vyoyk podafadbidp, fid texz pu cietm jem gi ovi Late Bafe vu zoku riha os jjeem ehnx. zghky://jvara.qufyovyovrory.fon/zmalawpk/bage-pawi-qx-zisiyaowl
Pixu Gawe Xcuzyeqsuvk Joivi nr Ajtyi. Oy hoe detg hi lek arno kqe voksn ytobvw, vtep Utpke’r ahsumuup niuqa as u digj-ciif. Nia cad waobf a cif ggeh qmuk quovi. imzfi.yu/3xJbaXu
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.