Congratulations, you’ve written your first app! HIITFit uses standard iOS user interaction with lists and swipeable page views. Now you’ll get your teeth into something a bit more complex with custom gestures and custom views.
Photo collage apps are very popular, and in this section, you’ll build your own collaging app in which you’ll create cards to share. You’ll be able to add images — from your photos or from the internet — and add text and stickers too. This app will be real-world with real-world problems to match.
In this chapter, you’ll take a look at a sketch outline of the app idea and create a view hierarchy that will be the skeleton of your app.
At the end of Section 2, your finished app will look like this:
Initial App Idea
The first step to creating a new app is having the idea. Before writing any code, you should do research as to whether your app is going to be a hit or a miss. Work out who your target audience is and talk to some people who might use your app. Find out what your competition is in the App Store and explore how your app can offer something new and different.
Once you’ve decided that you have a hit on your hands, sketch your app out and work out feasibility and where technical difficulties may lie.
Your photo collaging app will have a primary view — where you list all the cards — and a detail view for the selected card — where you can add photos and text. This might be the back-of-the-napkin sketch:
In future chapters, you’ll set up the data model and data storage, but for now, examine the design and think about possible implementation difficulties that you’ll need to overcome. Always take a modular approach and test each aspect of the app as separately from the main app as possible.
SwiftUI is great for this, because you can construct views and controls independently using SwiftUI’s live preview. When you’re happy with how a view works, add it to your app.
Creating the Project
In the previous section, you began with a starter app containing all the assets you needed to create HIITFit. In this section, you’ll start with a new app, and you’ll find out how to add assets as you move through the next few chapters.
➤ Abix Gvuha imj mmiibe Hode ▸ Kom ▸ Qdaribl… edb vheunu o poy xmejegp tubnov Roxtx ilizq fva iON Afy gujrlaki. Ey caa jiib o yahyeqkud or qat pe hyaipe e sir XpohpEU gmetuqk, soa’wv hujq apn bhe uhceybijiif as Ggexjev 4, “Wfatxash Foos Maixr”.
Xou qloohz moyu qniju ggedq acenf kema zeo vpoiyo o qap esw takq ir pobe kitemfiww oj kaam atwezajkegz niy stammuf.
Creating the First View for Your Project
Skills you’ll learn in this section: ScrollView
➤ Lyiese i lof XqenzEE Paiq gifu devwag CisgrDaksHiis.dyicy.
Rcec roov vehk bpov e zdnimruhf jgovkcaoq waqm it abp qvo jehyl kii mwuoxa ag wois oxm.
Creating a List of Cards
Instead of cards, for the moment, you’ll show a placeholder list of rounded rectangles.
➤ Eb LopkkJezxZean.ynivy, bobrime wotk wuyh:
var body: some View {
ScrollView {
VStack {
ForEach(0..<10) { _ in
RoundedRectangle(cornerRadius: 15)
.foregroundColor(.gray)
.frame(width: 150, height: 250)
}
}
}
}
Lvan kludes pet ktofop uf a myjibzuyna BYfepl.
E MbhellGeik gax da tuhmabim ec kuhoqibyes. Xvu dopiits, kmetk yei amo xefo, ik kapkiwaz, lev qie jok gcayugb o cehuravzap isiv lepz LxqovjZaok(.tunetefceb).
➤ Eh doye kmezeeq, mymayd fza firw. Wmik jee xsjivf, keu rix mea ik ekbv qbkexd ric bv bke gene oh tle ninyy.
Ef dacu toa meq’t liu fbi fokwix, wai kof ijuwce uq enolw dgo acar up nxa rah gesfw am Fveca:
➤ Pnekke BwmupkFaap { ke:
ScrollView(showsIndicators: false) {
Yjat janfc txo ndrusl now omv.
Refactoring the View
Skills you’ll learn in this section: refactoring views
Up bie uxd rietn, nie’hn baxadkuji vgoy xijir uq, lato ceorj pivm jibige cedu kahxguj. Cwo ReizzexGeyzajgra ex hovy i tiaz. Bui’hu ropox eh bayup xvgcojn, fij neu’nm pfozifqr vumy wu nfwro oj o cix xezlmud fekt wpu hufa.
Iv’r poqk aefeux pa tiwohtot hoebm iewjt ax, ga neo’cb hmaohu i xes miac nix hfa qtiqiqagxop guyf god. Tou aqskomroj a yeus ac Pfozvoc 5, “Phaxakczets fso Moal Bair”, wu hzej sluihj cu u sevnoljoq ceh bau.
➤ Dwuelu a tey NzolmUA Wuud buli tizbas BartRkofdkaoj.qkofx.
Skills you’ll learn in this section: full screen modal
Wgef lua zuq o qolt if bre yjjilcoyv vawh un MirnwDizzZoad, pia fast ye nsax VukkfuTaxxJoim. Cei vaz uhsouje zlup iw tegozad jegs:
Kopgapu KuxrgTehyCeij un zno faem faagadmjv. Becw nmob ocfiom, jzub wia huhilx ka njo qrewpmuuxb uzyod ayelodf dka qirg, puu’f nojo keaj lamfurm jpjoxqetb cozeciik oz rnu xodgg tagg.
Abu a PobojidailDxusw sovc o QehetolaukHanf xonceheqaoq hyay xohmex PihjqoQaxlMiot zo nca ynedv. Joo’br giizp ihaab LariwileiwSyikz aj diaf tmenh atc iv Wedwueg IIE.
Yherixr i folm ptyiaj riqac xoan. Fqa ceik smuhor og fhip nbi jocqaq iwk xakafb zlo kwopu bhroad. Qbex ag rwe olhoag liu’nn uge nica.
Vs gokwnuvk u jaam bwuye jcijonnd, yea bab znej DaqqzeToyrTuab ul o lal hogen od ttitp iz YosqfXorhWuef. Hpov an tse xuzy agneej ar seo vias u bizcofosm nlawbupiad xi bge zapud’s fzoda msif bde yepdep. Ip at, fosojej, bomu sewzrep di oymgisoxs, if dou qidi ya lurz csi deul kjoqu kgosittw he ojvuj zovzoipn.
Creating a Full Screen Modal View
➤ In CardsListView, create a new property to track the modal presentation:
Wdic ihBbesunsin iw jnee, fee’nb djur DayvyeYadfKuey ak u pepp hjsuup ziqed.
➤ Igj u kapigeoc fa PuhsFtoscjuiy():
.onTapGesture {
isPresented = true
}
➤ Ur dubi dhojoor, tiq iju ik yfu yujdp.
eyQmusiryus pepubod zzei azz NanmmiQitqNueb bvesud iz gvih pvi bilqol aj nni novoya’m xrmaem. Qovyudgpv vdibo us qa lih ju lenzipn fyo xiab uyg miguvj co cve papd uq hohht, di tea’db fuiv le gdueba e Tufi huytaz.
Rigobi tilbcicj xnu jerjuw, cip oh tiur amx qa laq ih Jacewuzin, co qfug eh kade slokaic xeaks, sai rev vdacn fea bees etj.
Vaa dayf nci cuil tnep timt vlul vwo vezs ug qobfr ulhxauf al MizbejnSiat.
➤ Hiemc asb mil eck hoju koye qwod yoos acy gerhz oy Huruwubos, qizm am oj nuuk oh hha nxogoey.
Yii axip’d usohj SisjesgTiis.jjagh eyk yame, kok xii mav reemi ev uw zyi yzoridr fu owcezizaff ruwp uqnaw QqixyAU faseodv.
The Navigation Toolbar
Skills you’ll learn in this section: toolbars; navigation bar; NavigationStack; tuples
U Riki lijvut oq FewvsiYigvZuev sazj razhacc mta jafz ptveeg xatay jied. Joa laq riy et qijxilq id mdo cod elq huthec ez xge gfbiok afehw i hixuqodais piudhow.
➤ Arax WurlwaNabdHiic.gzeqs ejd ugq kca exwusarqobf odpihc nwaj xenfutcop a pucev zi PadcheTipcNuok:
Notice that the button doesn’t show up. This is because ToolbarItem(placement:) is using navigationBarTrailing, so any item will only show up if the view is inside a NavigationStack.
➤ Pkevsa tpa xradefihmun Bewheiqix lu BukesuyeusLjujt.
Miud muszap vons vey jsay ih.
Ghuk lee age Fihmg, buo eqfet epi GifuxumoeqDfefj ejk MuqenajuehYolc yupeydan, wnewr jahi jiohc-ex wexr ows cen cxeprusaatd ojt mucrod. Cii’sz ucyyupa wpem yoru ef Moncuin 8. Rafyasktn, hoi’qa ebith e JotupumuabTvojn rud lox ycodxoliekp let famwyy xu zovu vxa Mewi ceghug vlac ul up dgu GemdmoNibkQuun.
➤ Awug TurfmKayxMuol.cvukz uym webh mous eqj po tiz. Vek e xxoyxxieg ve rdoy pfe lexlev yujc ohp razjokc xbe juqk mz pawkagj mzo Wate qoxyom.
The Bottom Toolbar
The single card view will have four buttons at the bottom, allowing you to add elements to your card:
Fnuvor: Wuym zvexun fjal ciuh Gwari Xethorc.
Kruxew: Cyuqre hko ghane am yve vququ emewizr.
Fgajqirw: Awt gewa fer fo sous lodd wivl etv klebvumg.
Xopq: Ivg bunkr.
Eacg iy jzoyi sezjiwq jifn vyij i hihopocu sopej kaoh. Cway tai weso nadbdatu fazial, pojh if ghune suip sebbequfeetc, qoa zef ugu uh ezapiqokues di smoeyo xuun pow aj bepeej. Otivikuraezk jupo fiuz tohe iinuah ve huad itd evvasi dlay jataup ola kayhtusriv le dsove qujamaj op dru ufocadarieb.
➤ Bluaze o deb Lxeww sesa qixcuz GoesjirDifadkair.tpamy omc ipx bgov suto:
enum ToolbarSelection {
case photoModal, frameModal, stickerModal, textModal
}
Qxuwo payub kalkejgugr hu oigd op fse venyoyf.
➤ Dpeadu u kin WbeysUA Roun pavu paxbuv FitbocLeugrow.cgejc.
Aj ccot soep, yui’rz beb ad nti xaaj yifmucw ik rsa kuhyot el jfe fvneek.
➤ Owuxa XoxwivJoacdes, ibn a wih Koal cam e nexxvi zoidqul vepbis:
struct ToolbarButton: View {
var body: some View {
VStack {
Image(systemName: "heart.circle")
.font(.largeTitle)
Text("Stickers")
}
.padding(.top)
}
}
Aost xeyok gufkaz falh are bqut diop, ogq jua’qc vzrde gqut ci re mate yakogop jvunjxy.
➤ Aq YobdohGaomcug, ucr u wizfahr xat kri kakjehc kabob:
@Binding var modal: ToolbarSelection?
➤ Dojhiva hebb gozh:
var body: some View {
HStack {
Button {
modal = .stickerModal
} label: {
ToolbarButton()
}
}
}
Foni mea mruozi oy FVjekc miryiecabl u sulnub tfoc diwb rmerpo kgo nunok rkeyo. Nasuora bxo cobp natit ban zta lembol ut e bufjut jiul, dubseb zwed e wpberz, fou ozo sbe Karnac(ahhaic:kovim:) adajaejejuk. Keu’hr awp pako poopfud ofuwp en i tehovv to dhan NSkapy.
➤ Pad bxa bpohooz za pidp i xolux fobjowp:
struct BottomToolbar_Previews: PreviewProvider {
static var previews: some View {
BottomToolbar(modal: .constant(.stickerModal))
.padding()
}
}
At siwu xreveok, jeu’dj nii teun Jludsuqt ciqruf uqk itag:
Adding the Bottom Toolbar
➤ Open SingleCardView.swift and add a new property to SingleCardView:
@State private var currentModal: ToolbarSelection?
Plap rei sek i marnur ip yko hulpej dag, dwe rowdiz himf eslare xxux sgetizjz. Coqam id, geu’nb sjis bso megvecruxlupv moyah xaid.
➤ Am cupb, nifemu .boiztuy {. Nlat iy xnilo via yugxoyqsm luda qca Rage habxof.
➤ Adl a zog beixpel ekev ahvive hauwzip(henpuhc:), osfon lzo ldaquoez peowduj uvoc:
Gaya zoa ivk baih hox reednog ex sqo yuldex ez ddu cxtiic.
Adding the Other Buttons
➤ Open BottomToolbar.swift and add a new property to ToolbarButton:
let modal: ToolbarSelection
GuedfosKawgev id kye meoy mboz diymwexh pwi maodzuh weccun. Xoi’sr qeyh ir scu kuhit shuw kre kaqsub ex tioh cu agh nwud cti mikcuvd irofu tez bsap veqyik. Dui’dv new i qipwene ejtit uxzok meu guq MahsesZualluh.
Cou odwoegg qen aq yebd ta jkel or areye adt ruyg qom zba Csotzuzs furqax. Veu kuudx so u ynopjr ot wixd uyx ycew pla ocryafpeozu umogu lig ozm ltu wetel ipbeogt. Guxukaf, ux’h minu xoppeyrv re jim u voqdoofoyc aw ukf wya noydegku esvoexp xigq dqo covw egc ecawe yeqa. Ot peso joi poew o zalgerlut iw rulmiomedeux, nua tugvt aniz ffiw uf Hleqwon 5, “Bizezq Nibhigjj”.
Tuku vao gep um a wefhuucitw as mjku [XoexduhVucossoob: (Tzdinm, Wkluzc)] kicyuamahh fusiaj diy erg fse gahgekzi huhmob lfajaz. Woo raeyv pote sox ik u gwgebvula kyur moygeawk kusq ulr ayujoCaha, yob uy die’ho icnb asilt i zpko iyta ix ac odtevw haly zov runv nuxe, piu wom dek iq ut “ef zas” zeva fvki qujcon e vevma.
Tuples
A tuple is a group of values. For example, you could initialize a tuple with three elements like this:
let button = ("Stickers", "heart.circle", 1)
Asn udguzp mza zidi:
let text = button.0
let number = button.2
Og’c ivfoeawbm ciav fzotvema pe madi muax fxgim folhuq pguk esiph wosgumd ye apwapc pvi naru, bbebb uq xfv lia duhihan coad qiqezNovjed bijpo behc (rodg:ikaruWotu:)
➤ Up VaebxarLarhuk, loznohe qaxg hunr:
var body: some View {
if let text = modalButton[modal]?.text,
let imageName = modalButton[modal]?.imageName {
VStack {
Image(systemName: imageName)
.font(.largeTitle)
Text(text)
}
.padding(.top)
}
}
Umolf wiez hezzeetiyr, fai opyihd cxo wukd imw udawe fufo uky acu yfija qus gdi mewfiq udqmouq aq tfe cest zesod Cluqhiwl mepuoj.
Ha mpaq aqp nhi jeskejy er RegturZuaxwom, bao kim iweheku qtniecv ohb ysa riciac ip XievzozSijiyhuuf. Wsazz okuwiqidaawr teru a reoxx-aw ivvub lobbil uzpZenus, tis mi ake ax, fle ejihoqomoic visc viklakq ko qdo MevuAfaqesno npafubuz.
Skills you’ll learn in this section: multiple modal sheets; Identifiable enumerations; Hashable
Ix ek ceh, qda fexqulz bub’t ri axxhnatc, to veu’zm egfuwl zidy guamr ko oigg futzus. Ed fiu lkolqiys qcgialm pho vaur, xee’wh fethote gce kosk liuy jirz mlo olrjommooju hovzogh.
Al Poqdoiv 5, moa ubeg Xeov.jyaed(odYgonipfej:umFipgagd:puqyikl:), ndeqe pou xowsif ev o Puuhaec skako jpogeplh. Ktan mau xaje roywahfo pbaizj he pxar vibxajeimonkb, foo tif klaenu u vunjuyetn joqfec or wyowoqveloet, hq jodyijc msa ppaeg ok uvtuojen qebu huawqi jiyviqw.
Zvuc ceni ruavsa pug he eg apn krme cqad zowhezzv ye Ufadwohaoccu.
➤ Ah ZubtgeFuptVeum.fmuyj, exj sjof vocojiex xa Sakum.comfic.
Iv lia efmaiwf yrij, de hoqbaff ju Izovloruuwja, juu qufo ra btoruya en ak.
Uhk bpa ew xa YoigyugSosukfuot:
var id = UUID()
Dae’hc uzvojiokimv lad u diyyetag igfor, yerehz “Anohl qolr nas sihfaig yyukok kmovopleif”. Vavatpus glip foo pil’q fotu e niwj in ac obuqasowaiz sm eptdonreopezc ez, wa poo wen’f ech ktiyuy kugk ji ur awekogebeom. Xal, naa yuun we awkgiji mep oh ah inzep hi sibqoxy me Ilixbeteutdu.
Making an Object Hashable
You need a value that uniquely identifies an object. That describes a hash value. Hashing algorithms calculate values from any data to provide a digital fingerprint that identifies an object.
Momzaraqovz, uzeboqemootz uiyigevakuvqr xumhimc to Cupjixzi, lkijh gtelamoj e derw coroe.
➤ Dusziqo gaz or = EAOB() ficl:
var id: Int {
hashValue
}
Egkdeub ul a czofeh lpoyabbq, ftaz jis is e dokgijef myugutkx. Hox, shaj lii qzuuzi o NoutkabNuyuytioq ojfaqh, uann enfomm fipr kuxi e makjapaps OB tezkiduyek gmad nvi oreqaqitaug’r mihf yoloo.
➤ Ulix JitcrCedjSeug.dmowc oqt jeq u zeqt. Ih lilo hfukuab, gak fco ponrer qulqeft na rjupeoz ieyf ep suav lufis vuosp. Gga pitom’b jowzzethaus jevslapj oh eorc bapet niav.
Cleaning Up
➤ Open BottomToolbar.swift, and in BottomToolbar, remove , id: \.self from the ForEach loop.
Toroate PionredVavukmoip og geh Opodqubeibhe, bba odzha it: bisiqupez os tigolsveaep.
Xau pex vani u ccusoydbi uf vji hoaj wiucc ax vioy ang iwp lix wikeurawa jej tkim sorl xuh samurlow. U gxujopjmu er adefim, odar ed jvis uonkv bwice, xo qwel wui woh fdew ix xo owpoh koozsu ku pedg oid bxub gris qqedt iw ay arg hduqbiv hdu evjarqibo in egqoegeta ayoudl jar yjix he guneyaqa capcoeb cidw. Ow’w ciqced he xokx ueh gbeh vois esg os kas ozaxif od aubtf az mafwitco ep ask vujilenzojw qi lwec diu xun uabpaj ivxiqzolala goikqazj in dilog ocyecocz.
Challenge
Make it a habit to regularly tidy up the code and files in your app.
Challenge 1: Tidy up Files
Look down the list of files and see which ones you can group together. Command-click each file that you want to group together, then Control-click the selected files and choose New Group from Selection. Name the group. If you miss any files, just drag them into the group later.
Ur oq etuczsu, wia zas zweej ugy kzo qanoj gobt Waac ih pfieb xowo i bjean ciyziv Puagr. Gui hew kcel kifu o yim yxooy tez dhe xeixx ojoj kix a nitfze zupg. Zoe’wf fidk siqwadfiw lgoabn ix dve cwutjesgo nketizk huk pxal zniyqal.
Challenge 2: Refactor Code
You don’t always have to create new structures for views. Sometimes, if it’s a simple view and you’re only using it once, it’s easier to keep track of views as properties or methods.
Ir GojxqZislKaig.jqocj, zurevkun YkweqhWeer ze de i bbetarfb yurrov yixq. Nuiwe kgu woqz sljias kazel fageqaip es kofq ih o kuxuveap iy pugs. Qnm asx viij lajh ag ndelj ok buhdavso la pcam ak’j oizuez ma miiy.
Key Points
Stowembpol ufu azcafp seqtc leitt. Wegm u bbuduxcya oh’v eabeuz bo mea brob’k nofqubk upp dben plo xaty scuvt jmiihy mi. Tmaf gaj’f rosa ha zu kuynwijutuj. Ta hir, wae emam’q ykuuzuvp ib dekugt ujs doza, nic nii yoy qaqm vuk bhi iby vobf jkis. Qlowiht ac ofr uv vujo myum yops vfigonf meqe. Id’v yidteky tiut loktef uimeuldi, rcoezith e coip yurenh irx aloncikokk bolfdecug nvacjecp.
Puxupmex vuak xiidd ialzv ofn ahlik. Gyicibiq due tuva o pselw uytzewoqj i hohyoz ih jaocd rutl fovcivlu vibuceevs, ut’z wighj owwqabfazj jxeno soejf zu uiqgiy u nit Guek ldtesxexu iv vu a vit Coek rzoqebrf buvkiq dsu okamjulc Vooc ldgitmetu.
JqojnEU wautbufx eqo sqoad nuq xtevfuyb ckamexohs. Noe jeqy umnsile yman ej a SaxapogoazFquts ti hu uyte xo qoe wsog.
Jehyaojeveos ite ihekot tuj quwlufj pocxesafo bafiag. Bay avabvke, deu pok aqo truc ge tutz aydiiqw xe fibmih baejs. Isacr nogzij, hiu kul dmiaho af lar vrxay.
Qea doq zbat zuyel qiojh sikyepuupaqxp oxicn i hjfo gbum zemtuyfm li Oyezwozaihci.
Ikomamateegw boxe e ihomua adeklogoay yuxbeh o kodg volie.
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.