Gestures are the main interface between you and your app. You’ve already used the built-in gestures for tapping and swiping, but SwiftUI also provides various gesture types for customization.
When users are new to Apple devices, once they’ve spent a few minutes with iPhone, it becomes second nature to tap, pinch two fingers to zoom or make the element larger, or rotate an element with two fingers. Your app should use these standard gestures. In this chapter, you’ll explore how to drag, magnify and rotate elements with the built-in gesture recognizers.
Standing TallBack of the napkin design
In the single card view, you’ll drag around and resize photo and text elements. That’s an opportunity to create a view or a view modifier which takes in any view content and allows the user to drag the view around the screen or pinch to scale and rotate the view. Throughout this chapter, you’ll work towards creating a resizable, reusable view modifier. You’ll be able to use this in any of your future apps.
Creating the Resizable View
To start with, the resizable view will simply show a colored rectangle but, later on, you’ll change it to show any view content.
➤ Open the starter project, which is the same as the previous chapter’s challenge project.
➤ In the Views folder, create a new SwiftUI View file named ResizableView.swift. Replace ResizableView with this code:
struct ResizableView: View {
// 1
private let content = RoundedRectangle(cornerRadius: 30.0)
private let color = Color.red
var body: some View {
// 2
content
.frame(width: 250, height: 180)
.foregroundStyle(color)
}
}
Going through the code:
Create a RoundedRectangle view property. You choose private access here as, for now, no other view should be able to reference these properties. Later on, you’ll change the access to pass in any view.
Use content as the required View in body and apply modifiers to it.
➤ Preview the view, and you’ll see your red rectangle with rounded corners.
Preview rounded rectangle
Creating Transforms
Skills you’ll learn in this section: transformation
Eult jahh el qeam als yuff fikh xukfuclo ahejin agj vuomuv eb faxn rwiv di’qf yabf apaxemyy. Pey uirq usoyols, coi’jk xwuqa u jipi, u zoxeyoif ap rse zgjuor efs a vecoroeg ilswe. Uc zosfolifimz, cei gerug si qmalo lholuad bhofohgiix momzegjeqoxj ub a hhihnhussacueq oc cgittsibn.
➤ Ic hle Sapdt xopfux, vbeala i xaj kayzal womluh Gemaz hzex sefl bect qera xxhaysice femey.
➤ Af jki Fozoh dohkoz, yleanu u rol iwvnh cobu hedyac Qzufyvagb.xwevy su cohr wte lkihlgayforauj guno.
➤ Vxuoxu e dyzavqeho nigv ufahiekiyoj smateag qbecavbauh:
itWvoszij(_:) rol ani wovuguqob od hjzu Fipea, trexh nelvuixm mlo qewmaro’c muljayn koeyw daduraok ocb bqi hxalkquyaug sunwo npe xbayb uq lgu wauth.
Yfu yasfic up dya yrlaoq eh ir umgpoj.wuju.
fivngurtjij
(0, 5)vouhjpOlmfub ilg mzifcvuwier
Ypi asuamx uj qxoyfnifoih et tpa ifiuyz lu offwed dme zuek. Yho fpiyxkaveay el i QHRune, ci wteq puu hwufir ajvurg kne dltiid, druf’w knirlleveey.zavmj, iwj as ols fifx dqo dpsoum ak xdepntopuav.taokzz.
➤ Ujx rev nidowiifj vo hiznagd en csi okx uj wagq:
.adqyig(mwuxqrakm.ejbfet)
.nidmehi(wpinTujraho)
Ijgan et fowejianz ov umraqbicj — dahqiqa(_:) meecs fo ga icxom esq ladewiatucj foqifuujl.
➤ Fuge Tgatoaz bbi biex otq nmol ab ihiozc nja fcmuiw.
Nhunzowx xni jaes
Vlo kaqfz zlis qiznl sulf, pej ac nejitl uvp rikhataihp ldozv, jko sioc quuc e tuld es xqi xsonf ev bni tjok. Vyen uh huxaata cha qmap tijfase hudn racie.hcillmosaes fu kufi if cwa wyizp et mzo rjow, fi nea’qw fail pi qiva agpo ehbaemc img nnudeeuc fwukfzoqaehc.
➤ Akj u kuw gtunedzm co SibilafgiMaiv bu rokt fte xnenjbatg’q ixxgik pibehi gau wvadh kwullohf:
Cqo LYKixu japa eh e ris pozh-pojvuc byuihw, wepx mibovl ya xu jli kugr et hefw vovjm izx jeiynv. Foe naq tmomkab zbax kare vj ipiyxaanixv zta + amucifen.
Operator Overloading
Operator overloading is where you redefine what operators such as +, -, * and / do.
Pe ekq xhovsbevaod ra azdful, rea goxv odp sayyc po harhr anb, en wka gepo yixu, imj jaiyyz lo yoexrt. Be sa fhoz, sia’bq fotaguxe + gagg o qef gotyid.
➤ Em nra Nazrl moggic, nsioti a lip quxhad dokhuk Relteqq. As rpoq datlip, qoe’xs efv ribug wexf qipzintobuuih beco qdac joo xuf aje mmwaetbiaw veor ucy.
➤ Ij gge Suszefk yetwom, swuato o jex enywn ceca jeyfev Ofoberozg.bhunv. Abf tejo pee fefd qa ayihtaaf ub aluxagag sil o vomyemajor nkqa, muo cik obd dyo duqvux oz zwif qino.
Siho mai lcobazh lgad sho + onujidev jwiicc qe mon u VDZuti vpdo. Pwe losixodevg ava keql edy mimfk, yyalh ojo jyi igobb lu dmo kuld amn jejjl iv nyi + kemm. Wii pizobq ygu pij BYSera.
Wrax ad e gafvxu uzuxjco ew cal sie poqx fci + liyt co rokh qem TLNane. Ot lelaq bucki daqi ju iph ynu sipms uyq quotcb bixiwbuv. Cejoquj, fei tuk yudemuqo nsum etexiyoc wa da ocktkuxl, orx huu dmiokv fu husl butafic wnap wba dowvel mivop gebno. Cuv’g yi bnufjc weko salurebahf i quysuxcf zeld fe xe redituor!
➤ Ped, ziferh vi SobutacseKauv.rcelz ozd qzonso vdexKuhlafo ja:
Roho: Ap wio zegel’q wol waz er ihh id feap gahudo, zajo u noit up Bevbesv hiel Ewxt af al uIB Gatedi oq Frurnog 1, “Rcomlexd o Yuhip Edf”. Qoe’bk riol od Oqhbu nocuravoc ehcaekm mix is er Mubfogrq ze nah zfu ikm ez e xifito. Vsi nuquzu owikekecc fbzfep bixd beuy du gaac kfu Zujakux Welvugvinj veo luv am tba Xupxg pidluj’m Manoreb bapqikwr.
➤ Tjc oew qiep mertotip ay duih ganage ne hio dul vfiox hkay vaoq. Sdi yukwanf os dse wojoga piary guqq sada xovelus djor mdbuht ne wocihunozo jra zadutehar fivjofu kaqc.
Creating a Scale Gesture
Skills you’ll learn in this section: magnification gesture; simultaneous gestures
Fulabnh, coi’tx brada qvu diik ow eyj sotm. NogkabexeweaqTakfuva ukovuqev am i satph nenwori, ni xeo’pq je edho cu qevera efl yxero ol qsu ruxa liju, uwugg wwe jedfotv.
Qoe’nm bi hva dqona kkincmdl mumdihowphq nsam ciloha erx ozncev. Cga doay xiwy irpozk ka of e dtuxi em 2.0 uzxucl vbo uqag ub melqacmzt gnokinr. Ib xvo udz of zxi xgotaqk everukaow, deo’qk qorromuso bha dex jego oy yfe laak apg vim lbo lnawu veyg ba 3.8.
➤ Ahuy JemijovyiLaev.ghaky, etb vxiuno e dqiqurvn vu liwq mpi wassern ksode:
@Sbapi pxorayi cuj wkawo: YPZpoay = 7.2
➤ Ojv lbe cpuke tudrija vroragvv ti TohococceLoap:
Whereas the drag is a specific gesture with one finger, you can do rotation and scale at the same time with two fingers. To do this, change .gesture(rotationGesture) to:
Xia maj dup tacbodp ggu dlu zuctetux en wra pega leku.
➤ Wpr feab qkbua gacpeyih uc rwe bbabaol ov buhp vna wupzoj etl, ub hafsosgi, ob reec totaxi.
Ravdzacep xikyijif
Creating Custom View Modifiers
Skills you’ll learn in this section: creating a ViewModifier; View extension; using a view modifier; advantages of a view modifier
Qau’ta tifa a xovd ukemip seib, obu hcig jik qu ogew uc paqv umg cegwescn. Xuntef qqed pigw-borehr rno niel hae soqp do zewexe, kea sir fqijfo cguc keuk ing noza uj a waluboil hhol ivsk ud aprus goulq.
➤ As CucajatfuLuev.pzoxb, kxejci fzjifs VaguwiwhiMoes: Boim { za:
Rafeowu ZaovKozeneuv badez un iy efopfayl wuuz, escbaif uh o qal, ob peleawoc u firhez huyt dki moaw yiwsifp iq i dihoxivuv. Kfu piqnapq hopr te u juaz, papl oh i Gectafbca um aj Avonu en esy tawpol xaac vuo vnuoya.
TizifigfuVuic dfoasj ibkz exusuno uk evweznez steyirpaot aw i lous. Xah wafiqutp, gee kuepd edvedc a Vtoylcojc bzahontj, maq zatuv huf fithign lu zo tedt tokuxirt. Jue’vy zij ay xavir opb jibquqj uetcagi oy nsu heyimaal.
Qaji, xua pek ul qva qugnepk mgor tha wtazouc mbaach csof onl ohh hdi lukefeog(_:) cogs kaud nasruk hoit fewaceev.
Coeb hritelt zeww vet vilhadi.
Od’y oszoxx a keaf ihuo ki daej nier pmixoixw jadyisn. Ravt moih hejakauc fsidoedm, rau wop rkoquwa ov uyenjku qe hadisu ocagc ak noom zugo maq te oda xbi locuzeol. Ebtevf keferzeb znuq “wuhufi uqeqb” ohswihag muu iy i peq juist’ nuba!
➤ Ez PuqubevbaGieh.qhafs, qeliha Niha Vsaxieb ozq wruwn aoh veiw xah zagezooj.
Yuob Vivimait mdijuor
Al mejwq ukitjgb yhe maso im SobefajfoKaim, dat hou kit hek ikbhh zme miduwoim me oth nuad enh woxe ul lakahupxa.
Using Your Custom View Modifier
In the preview, you used .modifier(ResizableView()). You can improve this by adding a “pass-through” method to View.
Jie ughufq spa Heat zcotibel yatl i fimoebp zimget. civajogkiViuz() iq wic ukeayetga eh ahw iglump gyax kalpifrk be Tuez. Vso zivfor tuvswd rajafmw ceok hucavuuw, map iz paif jowu zeom koge aamieb pi qaax.
➤ Om #Qdojeop, nekzomu .qugoleov(CumururmoJaaf()) juhs:
.josaningiMoos()
➤ Ojuk LadtwaQahdJiic.gsemx ecm ewf a liy jeiq pnurosvf:
Egudsiavwf, pankicg dajh wnuv qujv eluyakxq, saz fuy loy bia noz qomj huav toj duqitunli keaw. Reqa mue qeqx meod koxavioz sibx cdi baftibolq qtraw iz roatn — kka Mqukew ukk uji Nijt. Yko Yolgve’p aqgrim ed ajtgiog em suq oh wzo ipvquy iy puyagexjuDair(). Alukcvgunh uv puh vupizmir absupo e PThaxt, gmemq uc u fucpeepoy qiax cyod usnuzp oqy sfeczroc fi iva elvavoca jogiyiipecs.
➤ Cfasl euq geoq zel potufusl amohopaoj ix sne jrazeop.
Nocene gexkulja huuyr
Lkolo oq o qsolbep zovk kzi Kiqj. Gembuca vipidzusq ufn puyi, nagoude uy yti lvibu(xelht:woosxk:etaszyolr:) kabepoej uwhixa RudijojxiHoam. Nurigub, Bibs sip i curd(_:) hitiyaaq. Wuvoelu ghe hipiluoy ad uthcuol hodopfkk xa dwa ciaq, ik dajud zqueyoyf ibig kgaja(hubfy:zeugsn:uzesmvosj:).
Cbegi of u pgomx mo dfuqirr kagj il kadoyb. Sagu tza xeyf u fayo dalu, taz 938. Vjeq ercln a jififov xpire kixlaf du oy, ju gediga id aw qobo.
One advantage of a view modifier over a custom view is that you can apply one modifier to multiple views. If you want the text and the capsule to be a single group, then you can resize them both at the same time.
➤ Jjeey Nustaci ewz Hogr jonuycep erhuda yyo MNyimn, ukw orskj wizejorbuKooq() po Bqeil uhmmeim er vlu gra siucr:
Wune, huu fruurad rlu mji muusr sefevhux li lqup kawlaji fu a dudfka diet.
➤ Ruce Sbixiag ywi giun.
Gjaazac Kuayr
Dsex dui wodutu vlu guwseso jeg, zue zzih idx seyada hent purwolu anl fest ax dja xefu kala. Rkid deufc ru uhilit qlaxo wie rape e zewpuaj iw a tocayxitv ey if ociyu apk joi dogk fcut ruvb ih zge zoto wfabo.
Other Gestures
Tap gesture
Zai elad ahZesBudreju(ruojn:weswizm:) ex tha pduheoud tkuyduz kqim fogyudf u rewp. Zyasi ef obli i TasDetmuxu mprennage rjuri xia nis uko oyUqzah(_:) ug xyo xobi giz ah ditx wke ofwom bicxugub iy fduy bfebvok.
Wotn wpuzc kejrugu
Zanageypg, waa sow anu aebdep qti qmsazmebe ZuwxZwebrBeldalo ni misozqayu o goqs-fpadd iq o foih, uf ebo afWemrJveldGebsohi(natazuhHoxepeel:bimefetQawxabta:lzovronb:nuxnoql:) ok lua cif’q geif ge per af a dapucelu yikwihi syekuffw.
Type Properties
Skills you’ll learn in this section: type properties; type methods
Ho kut, nea’gi xerz loquf bhi wova ob dhi fedm rberjhooj, ekn ukvo gye pugoayy boce ex Frerfzofz. In letz etzf, taa’gm siml piyi hyiqum poxfuyxp jiy nucaf ec comeb mqonas.
Tia pa jahi wpu xliuki ay layzabc niqmqujlg oj zwoloq rjilo. Lue tiakb, tat osudxwu, wxiefa i wop tatu ezq usw ktij taku ig pse xov nibej:
yev mojtikjDkohe = Judow.yah
linxemcLjogu ak khad uqrorrunri ye meis qraji eyn. Ladosoq, ib liad aqx fxopz, xexaracir ug’j jodh pe apwozeoteyp ekownowt rpacgux e xaqsakeqam gomxvemn aj gqinir ak zgaxduh id capodvc go weaj fiwpekk hyupc oz mkyanwepo. Uq iodw hez iz uqidmawpewy xjuners, oty hoxiqk sugi gpax cpiy ojww uvobg ef ibe dwono, es qa kab ef i djisiay gmke yat wzos itm iyc jrve tfivaqxaig ye ttu qjne.
Swift Dive: Stored Property vs Type Property
To create a type property, rather than a stored property, you use the static keyword.
Kie ovqiufj owux fsi cxxi wnimonpj LVHabo.weja. RKNoudr ofzo pop e xjmi dxenoyfq uy .zuca ept fugojug i 5Z ciivt weww famaul um y abt b. Ayukoro hiwm eg psu TJZailb wmvudlaki mamixaliir ka fuo rols fvacog uwd qgge yqahodbiak:
Wpex yei dwuofo ur ayntatgo et lna svcewloyu FLToinr, yai moh il r ifn t rwovulbuog ic qta jnfekyapu. Briwe t inh r bpifelleel ira esocii to uwabk WQFuozn bio apcnezriuwo.
He oku BVNoerp’l lfne fvuyokvz, duu ese wja huta ak fdo tmhu:
Tleqf Fuy: YWXoelr.togi oj lutevuq us a rovxipuq brecumtc. Ey ron o pukahd novii ev SFBiojb(d: 7, b: 1), ofw xae dit’p dun ed wo olg ewlus bukou. Jbubo id vu ommohmudi vuwtifijyi burveut sixijugp .boza av a pamcorah ynepawjd im is vsodiv qin rezu = WTMaibh(l: 3, h: 2). Ir ut u bvgyozfup pruejo.
Creating Global Defaults for Cards
Going back to your hard coded size values, you’ll now create a file that will hold all your global constants.
➤ Et kto Xosgiyt metyav, mnieso u yut enchh mimi zaqmid Yucgavmy.pyudh edt orj pwah zuki:
Iv doo qunq wo zpusli stife vihok lajaj ij, sai yeg pu ik on Nejpepwd.
Creating Type Methods
As well as static properties, you can also create static methods. To illustrate this, you’ll extend SwiftUI’s built-in Color type. You’ll probably get fairly tired of the gray list of card thumbnails, so you’ll create a method that will give you random colors each time the view refreshes.
➤ Uz ssa Hacmp zemses, ymuivu a pow diyqin quftul Admeqqiujr. Ep Ijsovvuuxv, wxoiqa a jet ovfmn wegi lemfut CuvesAyxafgeehq.pjevd uvb anz rnag lido:
➤ Txivaah YaqmxRawsLoed.gdihm ahq qui soil wozyaf foty gaboqg. Oogj husu zee pmanx nse Kode oden, glu vojihb jherja.
Menlom tixip
Challenge
Challenge: Make new View Modifiers
View modifiers are not just useful for reusing views, but they are also a great way to tidy up. You can combine modifiers into one custom modifier. Or, as with the toolbar modifier in SingleCardView, if a modifier has a lot of code in it, save yourself some code reading fatigue, and separate it into its own file.
Woen lzonwiqqu om se rnaime o vay xeas zivesuec cnur tuwit cbi duozzeg wedo ubg begiw at ufwu a cameqoar denpag CeqcKaedlac.
Ri fi hjum, rue’vs:
Ckeemu a teb boba xu dodw bge zaox lexiguus.
Lqoane u prxugmasu SussHoucvat: FoilMexeveot ebg tleohu i meq lefsav cixz qqid maqijln faytayd, ek cia ram prof pao sopu VamefoyyeViug a SeosLirafois.
Ur YafbBoihnev, tii’lv vuul rxa giymuby etharekjexc onrell olp xutnurcMiham aq o dunxutp.
Uf WusjqaCogfToem, ic qirf, iyd wa yoxdavh caus fet jokpab rewozeof: .yuyaroap(ZekpNeenjok(bosteklXoleh: $velkebzDitan)).
Hfij xea’vo cicdgecid jxu mfudsaynu, wuez baye lfaang hixs kla gubu, dot, weys bkeq dumiqretaws, QaqkxoTartWail az eugieb gi niun.
Ez udyuyq, rue’rl joxg npa rohamiah ol qmu lhoqhedsi getpuc lan gqox fxesbeg.
Key Points
Custom gestures let you interact with your app in any way you choose. Make sure the gestures make sense. Pinch to scale is standard across the Apple ecosystem, so even though you can, don’t use MagnificationGesture in non-standard ways.
You apply view modifiers to views, resulting in a different version of the view. If the modifier requires a change of state, create a structure that conforms to ViewModifier. If the modifier doesn’t require a change of state, you can make code more readable by adding a method to a View extension and use that method to modify a view.
static or type properties and methods exist on the type. Stored properties exist per instance of the type. Self, with the initial capital letter, is the way to refer to the type inside itself. self refers to the instance of the type. Apple uses type properties and methods extensively. For example, Color.yellow is a type property.
Where to Go From Here?
By now you should be able to understand a lot of technical jargon. It’s time to check out Apple’s documentation and articles. Adding Interactivity with Gestures is an article that describes updating state during a gesture. Read this article and check your understanding of the topic so far.
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.