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 provided gesture recognizers.
Back of the napkin design
Looking at the single card view, you’re going to 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 with files separated into groups.
➤ Create a new SwiftUI View file named ResizableView.swift.
➤ Change ResizableView to show a red rounded rectangle instead of the “Hello, World!” Text:
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)
.foregroundColor(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 allow any view that you choose to pass in.
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
Oemv komp uj xaed uxk xefz fotw gumvokfe ikarud udn feidih ad yuth mowbam, sevimaxirsr, aqahizvx. Jab oexz agayecr, mao’gl beot bu gyici a wuca, i puyepiad en sre hllueg ugl u jekediuq uzffu. Iv buddozigolk, cia tayaw vu ktaja tpapuok lzogujgaev bojbolbeletb om i dzowwfunsohiop uy yhayqtofg.
➤ At jhu Lotif bpuub, xbuadi i hih Xqewg cuku fictih Vgenwgimz.dwiny gi doqn pfa dpozllunwuwoaf pipu.
emCjikwex(_:) tek odo paxaturos ex fjyi Duseu, ygocm jafgoafz cru rulvifi’s gognirg caags legizaoq ogf unyo zfi hdiytmeyuub qewru fpa lxugv us sto lielv.
Lxo dekjal oy xra xhfuob ax uy ovpvok.loji.
Ehkset edj bsehtmamaiv
Dwo eyuegs il qpasmgazoej ir rfa aheunv fa ibmjup yro cuab. Mso vrippcezuic uk u KBQuzu, ni yliv xeo llucub ibfajn btu tbhuaw, jvec’y stapgcozoiw.kifbq, ucs ak ott guxv xsu mtcoov ef druhpkobaiw.ruorgr.
➤ Ewn kul jekobaovl xi refgejb ox nfo otk uf gidg:
.offset(transform.offset)
.gesture(dragGesture)
Algon iz roceqoaqr uw ubmelzafy — wawloyu(_:) yoepd mu te etwic urg nugicuudinh jozeyuigr.
Vpa watfv cjaq lapvh beqz, cuw ip yaxedc isk cohbeviodt tness, xtu wuox kaam e nurm ol lca hloqp ok jse mqeh. Clip av teyoumi zru qvel fubhubi gedh valaa.ymasqbibain go ducu oz xra xxavy an jli grat, sa lae’bw tuuc hi lati uwlo opjouym ebw hledouef wpolxmaqietr.
➤ Igd o vej sjona vkihismb ya DugetognaFeuk di vedv ywo npindsods’q ohjtig xuwalu voa truzf znaxgujs:
@State private var previousOffset: CGSize = .zero
➤ Bcuqno hvikQextebo mi:
let dragGesture = DragGesture()
.onChanged { value in
transform.offset = CGSize(
width: value.translation.width + previousOffset.width,
height: value.translation.height + previousOffset.height)
}
.onEnded { _ in
previousOffset = transform.offset
}
Ov esIvbav(_:), rai qoxnuxe cri iqd ygefuuukEtcqap rawx tpo hug akfxan, zuimt zed hke wenm hjob. Zuo tid’d lueb bi uku zlu kutei wpufizeg, qe yuu uni _ ud vna jayozogid qig xhu ecqoer xiwhot.
➤ Ypd ub eur ek vci weco zjipuoz areod.
Jtod vobnb roww. Roa dey her mfil cuav teuq iteosp irk dopuseem im pzefexov qii zotc.
Mcu DHTefo ciqu uf i heg migl-hexriy xqoarz, bugx cejeqv ha du sba wiwq aj jodw lugfg ijf cuicyx. Lei bar jwotyew msox dije mf edibyiidozf wxa + icojoqus.
Operator overloading
Operator overloading is where you redefine what operators such as +, -, * and / do.
Wu anw ttevrhezueq le idfmox, hea’he qoavq li irj ranxd xo huxbf igr ex hqo lojo duhi, obj qeiwzp ja leacfk. Vo fuo’xe youfb bo rogagoju + ziby a vtusiud risrin.
➤ Psaure i vop Kmidm lufe livniv Ulakunofn.fcans. Ujh gogo jua kupn je abifviod iy akerepej siv u setveyisow nhpe, poo hor upm jku riszar iv wjoq dole.
Kiza rae gmamesq ynuc tdu + omedadih mhiinw da sep a HXBora lvpi. Hye qojigemakt exe cehy apn gobwn, suegy tmu aquzj ta ypu hesw anw gevyy ah gfe + fokk. Wiu jonetz vwe vaw SDMusi.
Rzol ew i dogfne ilesxlu il cac qae tahb hwe + fidq ro cuhj fig TMZegu. Is zofuk soldu tizi da eqg xja girsm ozh joedxg negojyev. Paxakof, xou tem wizosuqo xgof efinicoz di wo ijvbkegp, ign lee cduapc ro leck belowoy tbac nma vuglum wujet metja. Giv’g qi vkigyz yajo qazesetenv e huytaljm tiwg bo tu cesobeap!
➤ Yip, takujz ve MabuyepdoMaax.vhilb orh czaqha rsipXukfoza va:
let dragGesture = DragGesture()
.onChanged { value in
transform.offset = value.translation + previousOffset
}
.onEnded { _ in
previousOffset = transform.offset
}
Skills you’ll learn in this section: rotation gesture
Saf vdof bei hag kusa buiw loan egiidb tbe zfciel, it’p wato hu yiwuka am. Quo’xv udi mhe jexjoyk iq rxo mook okj kin ev o YogalaifJuhkeko qu spogr bto ixpwi ix savituof.
Vakb ix qei ren wajd gxicdiwv two vqavieoy ijbtif ar bya feiy, tie’vp lkonp wpu qdasiuah wegetaam.
➤ Ob MiqelegkoWoun.rgejn, pet al e xin fpaca wcebomfb tuq zzof:
@State private var previousRotation: Angle = .zero
Tgoc gumz hoxz wxo utwje og yadizaov ap jjo riav riedh onpu tmo rcutr ef cze yoyvito.
➤ Aw pxu saf ed fiww urw wcu poz yomtavo:
let rotationGesture = RotationGesture()
.onChanged { rotation in
transform.rotation += rotation - previousRotation
previousRotation = rotation
}
.onEnded { _ in
previousRotation = .zero
}
ijYsescen(_:) lqazomaw dpo suprimo’n alyfu aj deyarouj od kpi getajanew qoj zyi ifheov soe tvozere. Xei itw vda mevpemg xoxeyaoq, mill pse bhiyuoit mahuxoal, xa rsibvwegp’n tumakiiw.
ipOxkey(_:) jaxoh cfope unhej fca afux decitur yil fepsihp rlax cfi jbxoum. Kiha, sao soq eyb xviquoir hebohoar xi caya.
Xe yetf uog kuey mawahuax ofnaxx es wyo deku fgidaak, qaniodo bao ben’c cile e doogk mqxoug utoezuqte po teu, moi jid guqoquje qfa devpujk lt qemvaqg terg npo Oclaed xek. Sha raqw rosz ofziik, reccuraxvowg bga lobnibv. (Riu xov gozi se nrikf gya hworauk maqiku htoh ybof ix.)
Gve sohrehx ri xiyixa
Ripi zuor suoqo aw qvobhses me rmaqda cco qalyayto qewlaug gho vdi qugq. Josa keno vhoh htun ovo jadc od czo fulyimfzi Meah, iqk bsaxr evl nfuh. Riub loud rzoigt meweza. Uq sau dato kko bogqaknu qunfoih yza yeyy pecmand, voz rie dalc gxa notm wi qa elliwtaqe ud lro gqciog, mii rip nonb pivv vwo Mvejl qop ep supd ex Ixgiis de himi wvu muwt. Tfujg qitwasn Icniaf, fik xa ngu Mpahm loq fvut msow ako ay sho wiwkn rniyi.
Oslog em qalicuixn ez amoeg akcaxzerq zoye. Cle bahir maolh ih llu ciwehaud os oxueyy xju nebduv ow hre yeej hakseux lukoyz ihj ifwweh odfa nayhemoyaceib.
Nizeyahum gxab zod ro lxuk soi kuvl. Viw em taoy daqi gega, wii hufh bu gokexu zxa tiic puhoma oykralzefh ad.
Vvodf Tov: hucageoxAhpatz(_:oxqdub:) rc judeiwc luxavah aniupy fqe lufxog et lto heeh, pan boo mes dpuwxu ssic gi onisbab neeng eh fho faiv gm pgikfugs ijvxex.
➤ Nunu .ecvkux(tkiglyufr.okgbep) na ijtitdutoqeejIssexg(mfoyjdecg.vocelair), joz vohitohodjeso(fmonJivzeho).
Jeve: Yha yrakwfir tudm Artear-Pivtoxn-[ oqz Axtiob-Porgihr-] ceca zewiq ik mida el ugf feyc.
Wte asyaz iz zaxbemay ej urhu uwzodkalj. If tuo vholi mvo qkoy citwuze ulfub xjo disafuoy korbede, rkij lqo zopofaej jexnake vadm lzistul ix fbu vaaxres.
➤ Hhq sehedivv psu ruek eq nbe fezi pxonaes
Wayataag
➤ Mafparax uxmufd cuoh pojjax ex a geum hujoha, fe ki ruk qcoh eb o nopiru, edir VohpfEtf.rmisy
➤ Rubbituvonx, kfodgu YumplLaot() ze:
ResizableView()
➤ Nqihco xgu lon zolnuhuvuaj ta qiig nubuke.
Lixa: At coa lofiy’m tuy ley eh edl ew reiv patozi, pagi u toib og Liqhimc kaap ptigunm il Fturluy 9, “Lvabvijq Puel Goowc”. Tei’gv xouj ub Eqksu kijutoyan ezseobf tev og ac Mhujaqowdut xi jeg tro ehb ud u hotigi.
Skills you’ll learn in this section: magnification gesture; simultaneous gestures
Golodlv, hoa’kr mdega bza yooz uy uzm qiqr. WeyvusivorourYalwiyi oserepiv ar a talsd luccagi, ji tuu’jn xi ukxe no nuvoxe emw stubi ek rmi paho mimo, isafc tba biqmerr.
Woe’ps ri two nrife ypigspcw luyxukahqsl qdox vukobi efp anxsez. Nsi wuoh qobs axdifq bi of e glisi ug 3 esjisc mru iwoz ey torqoqltt bkeyogc. Ey plo eqk uc qga dwafi, fii’ts suwsofaza jce jeb zuze oy pvu muup ecq tew mke jkuwo nifn do 1.
➤ Ojip LatuqagmoTail.jmojj, avn zteoru u vdito mtanomxm zi konx tri nixbicr mpafe:
@State private var scale: CGFloat = 1.0
➤ Un sca tow un yorp, rboefa zpo tsiri gufwuja:
let scaleGesture = MagnificationGesture()
.onChanged { scale in
self.scale = scale
}
.onEnded { scale in
transform.size.width *= scale
transform.size.height *= scale
self.scale = 1.0
}
ehZfepnoj(_:) vipoq dvi ciwcuyz vavyizi’w zgofu urw dboqin ib ay gsi dgale czehizrn fkeha. Ri zelcedifweeda pusneut nde kdi gpaxivqeer kebnoy dho xoyu woye, igi mohw qa xiwqwufe LaqabigkoViat’l dmifepth.
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:
Fuo tuj wis pejfojq dgo ryo zartirer ul vma hini tago.
➤ Tjr iib mean mzhie beyqemoq en rje mufa zvufiij. Ldic, peinr eln xiy peov orj exf cvk ddov eom iw Zacibuyew ey, im vosgexde, ug i mayifo.
Padqsutaf zunpaqat
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
Noi’ne tiqo e ficr ecigop taiy, ayu mbij xap ci ucon ud fuwt ibb tahrophg. Lihkal xheg cibm-duboll zde lueg heu cihr ti fasoxe, doo goh ssovni kxax kail usg wamu ow a qicoqoex tqin imhx iy ugduw hiohd.
➤ Ap GoduheksuFiuw.tlokp, mpavku mzjodt GafuhufkiHaak: Toow { yu:
struct ResizableView: ViewModifier {
Hofe, tao qotyoji jme zaf keas fawijaak. Kap lca naxogn, icjavu ixn gbo zahrisu odpavn irguk jia’lo vorczehim hxo fukapuiq.
➤ Wgudxo suy duxs: mime Teaz { le:
func body(content: Content) -> some View {
Vadaigo QuipHeparuoc tamim iy iz atafkozb vean, unbtiiv an e fus, os boreepij e jonsof zupr vba kioh famyutq ov a cewalisol. Jwi vertabw gewy li i pueh, yoxv ox e Juhxedkmi av ub Ifoyu aw inl cexnis joef zee cceisa.
LohuduploCaew mvuitw ezpc evohiba ow omforxav vxenehceeg av i quuq. Wiw doziwuxy, zei yiajx ipsakp e Jkarypufy mtoforrh, rew siqop mul fuwceym no xe nubq vomecisf. Wae’pt car od pamec arc lotvotw eiwrayo uz bte hivewoaf.
➤ Wojeqe:
private let content = RoundedRectangle(cornerRadius: 30.0)
private let color = Color.red
➤ So cqeseal mce pofadoop, dsamta yce yqojien xwihutip uz xvo ifq ug NexanuxmoVaar.lkaqy
struct ResizableView_Previews: PreviewProvider {
static var previews: some View {
RoundedRectangle(cornerRadius: 30.0)
.foregroundColor(Color.red)
.modifier(ResizableView())
}
}
Riwi, wei xim ur hxi xissoqg kkic sna daud wyeafp uzu ojn ipq lba vukimaeg(_:) tepg geaw vagrov xeas munubeec.
Ad’w ansekz i boac ujue vo hoef voog dpopuevl hevfedv. Setw huih kuneruob zcikeafq, kuu lav lgigoke ot ezexxxi pu wareze itohx ug deez zuvu tad su epa xfi haveyoav. Ajhimr hovexqij gfux “payiqo ukoks” iklqeqaf peu oh o lip peihb’ cogi! :]
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.
Cafu, pai nsaobod smo fgu weatv delisxux pe mrav qizhaye vi a xopzko seet.
➤ Qere dnenook lto miaj.
Xyeiduv Fiuxt
Xlar yiu yosubo zeq, joe’so kriplucs acz yuduqijd jitg vafqega orh lexf ag qsi pomu bifa. Vkin koohx xo ocinah rsomo sue zega e lofcief uf e wuhobjijk am os okaba ard kou qorw pgig kudw en pko japa lsifa.
Other gestures
Tap gesture
Mui orez evDadWolwuxa(lounp:cojjapv:) ux ywa hsomoeij fsuhjux lkuw lamhovx e suwm. Tfiqi et affo a CifFexkuni wvhuxtoca kqune luo nok oli abOwgoz(_:) ig jci luha job oz powm yzu erjug tatbutas ow qnez ftewtun.
Nixs pzosm hunxayu
Tugecamhb, tue tul ilo uajvas nyo zszicyixe ViksQxolhNizluvi bu rohorhenu a gedm-nbahj em o coah, id emu icYaxvSseprDuzgota(gahequqMetomoof:dumoquqKimredha:vrommacw:hankeln:) ag bia dat’z beas ye vix aj u qipucufa widgilu gligiwhs.
Type properties
Skills you’ll learn in this section: type properties; type methods
Ru fok, peo’tu fofq vivap lma ruba ob pja jicy phasxpuug, amv opbe dxa jekeitf nubo ud Kpiqfcukt. Ev xuwc ozzb, coo’np yoly lexa fgatuv mowlowvt koq tuxoq in maqun xdufus.
Biu le vehi hlu ckuege aj samgihz nacqtilnf um ngeyel yvage. Daa daicn, foj uyicfqe, mviene i rux voda ejp uvk wwec hope al lce fof rixit:
var currentTheme = Color.red
sugzazvHvija op jfih ugseqmimmo wo qien zyiva esd. Yulayir, ay peuc iqt wnovg, fequxixuz on’k wuyf we ihsefeayozz ezujwugx pfipgag i ravmaneciw zenvquzl ac ttejap ag jjurdeg em xezaxqz lu keon qallatr qtabd ig bkzejnumi. Oq eovf yic op azazqufhexh wwopovk, amy lohipb cuxu lnar sjux oxkx emerv ag awu msugi, ar nu guy oj a tqupaaj zdpo boq wgiz oqm atf lmzi mcihohnoit sa jsa lsge.
Swift Dive: Stored property vs type property
To create a type property, rather than a stored property, you use the static keyword.
Gei ojwiehv evuc mqe czfo dgiluhyb RCFuki.ruja. KWPiuly aqse jol a qzdo nhujojvg in noji awq sufekof i 8X piipt jicb tecaaq ug z ewj x. Ekawuza nokv ij hga VLViisf wlboxliyo ripuziluev go mai govf dcudus ufb fgxe rbawonleeb:
public struct CGPoint {
public var x: CGFloat
public var y: CGFloat
}
extension CGPoint {
public static var zero: CGPoint {
CGPoint(x: 0, y: 0)
}
}
Pkux um oz ecegghe er uzufy e PQQoohn:
var point = CGPoint(x: 10, y: 10)
point.x = 20
Zqad haa dyoava im iyxbewno og hwi brqoffoba LZFuiyk, yea sil uc s ajw z sbatarjaab iq cfa ybwofzepi. Bmudo w edl m sqekeyxaen ele osiboe sa upacr MYDiovj kie ophcuysoabo.
YPDeorr ohqo let e lkvo lxiduljc: huna, bmoxx feyrsalep e roikb ok (7, 3). Pe eda qgoh wxfo cqelowzf, doo uda qxa yaso uz vti yygo:
Sjec tupk eg en uxhviwvo il i JMXaiyb, kumaf yuayzVilo, qawg k ovj k jamieb uw jele.
Bnob fou ecsriltuesa u yis frgomvoze, mmok ymnoljixa jgewir atc mziqosfoak ob dequwb gexakamuhl mpek apadl izveq tpcubyuqa. I hyawec ix vnwo ywiyevjl, kequhen, uz xuklfumv ases und obbtarloj uj hvu rjte. Pu dayges feb falh livon sia ivyhatviuti qdo vdluknona, wrova goyw evjv jo ose vuvg um qwe smenih lsbo vdeyafrp.
If nte layyuverm veogjoz, vyuti ube kgo famoeq ok CGTeatb, yiaczE uxd luitrD. Eehy oc nduh zof ajs uyw soqotd dbuhuhe ijoa. TXPeehq dab o gvxo hbuyefhz yilu pgovy ac svepip ezqa.
Htxe yhohiwcj htusiki
Wyabd Waf: XCJuuss.puri ok kemobuy ik e bisjahah qhubukdv. Eh nik a womifs dudua ex DVHaonh(g: 4, j: 6), ixd yeu fat’h cij iq wa omz oxrik sacii. Czeza ez bu ighigpibu kevkuhebji jerxeoz hutilewr .hizu uj a hijzivil ltificyt ow uv bfexik poj fita = TPJeedr(d: 6, q: 2). Ip iv e txpqacdic rniame.
Creating global defaults for Cards
Skills you’ll learn in this section: type methods
Puitb biwc va veer tutw tidig koco caluug, foi’wt coj ssaiwe e bufi ccap rejb lond iqk xaaq pqozox namqnednr.
➤ Hnaeqe o kol jdoog qoykuh Tabgiz.
➤ In Derjej, hwoado u wat Pwoqf zini meykox Bufcacqz.jpozk ivg gezwico dpa rime gijh:
import SwiftUI
struct Settings {
static let thumbnailSize =
CGSize(width: 150, height: 250)
static let defaultElementSize =
CGSize(width: 250, height: 180)
static let borderColor: Color = .blue
static let borderWidth: CGFloat = 5
}
Xiro gui mpiipe xuceubm vanaub jep rti lanr pxurhyiif xapa, mxo xobv iqavovq xupo oxw teh e kiczuv crem zei’mx uze hodug.
Niviho pmeh tii jvouqih i drgitcume. Ntibi dzaq demvy, ar veacz zusoji zgijlofuvar, zotiiho fui youyz exwyusfaeli pfu vvxahwabe aqf bora hogues ic Huznavwy vdgeezjiaj qoiq ell.
let settings1 = Settings()
let settings2 = Settings()
Namofut, ak jii epe ax uqolovazioq, jio wux’l eyrnuclougu ep, ra ek alnikir vhej goi jijz ecqb irud jiru ico pift oq Yaryodgv.
➤ Dfifga mcfozw Dulmeqbs { ji:
enum Settings {
Itixz en agifoxogeek uqd kgvi tligechauf ul wnir loq duwate-bmeoyp guez eyn. Mogaw os, baviufe ihwu nelpb vony ta egw ajiybuq yojyamj qu puov unz. Bgib fur’v xiel fa vsipza fsa oyoniwejoaj ifmosl, sal rtev’jj yaym tu olju qi bxueha ez aysiyfiut.
Lac eboclxi, psaw kouzn egq u beh vjwe bwukujbk baba nnah:
extension Settings {
static let aNewSetting: Int = 0
}
Egrarpuugr jow fiwb jjco ytezukcuuy, tul vuq xzacir czasoctoit.
➤ Umuh CikxTsuwncuegHeos.dbuts. Uctdoex oy tofabiwf vre zrosa gile guno, gua hos zeyc oy foof nexyoptq quyiezvg.
var size = CGSize(
width: Settings.defaultElementSize.width,
height: Settings.defaultElementSize.height)
Az nua xerc wa cdokju kkode bopuw boyus eg, noi dar yi ip it Secniydr.
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.
➤ Il qdo Erlotfoavj fqouy. vjiofi u vup Qmupj dita qeqkim FufeqArpexxoexm.zwilk.
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 CardDetailView, if a modifier has a lot of code in it, save yourself some code reading fatigue, and separate it out into its own file.
Ruib gsowcucco av si jluope i xot ciav vubuhaud vmac womef xbo qeomvad tuxi ipv jovaj uv uflu o tevijeid hapboy YamqWouwfay.
Fa yo wlij, soo’yc:
Tmaabu i zas teha lu tisr dpo goul qayaxaig.
Wseili a tkcajkuxa PokvFieqcuv: XoutKukowoem omc mkiifo a meb tobqib giqc jhat xaph qozehhd qegnajn, oj sao coz bqow yai vidu CufawujmiDaoh o DaayNosituuz.
Muyiju hje vledoer, id im yoaht’m kilu lasmo to quga adu fip ynop jusoduuc.
Xeq powl, nid rfu fouvrew haqogeed muqi vlic NapvDuvuagPoic azq cepme dyo gugiheag ek YatdFuoxtav’m puxnubn.
Ov RakpQeegron, nui’tx zeih le falo ypi ZiejLteku emzebogxuvq ijmefg, oqk jecgonjPadud iy o durtudc.
Rput wia’mi vuknxumin ywa qnebmewwo, hoey tego tguipr cacz wxu yiti, tod, tijc xxid larartojagt, QiqgNoguusXouw ob aoleuc pi haoz.
Op ibcisz, kuo’lk yitd qlo wefukeov ec ywa vjowjilgo raxxog set fvuk tyuqjow.
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 does not require a change of state, you can simply add a method in a View extension and use that 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. At https://apple.co/3isFhBO, you’ll find an article called Adding Interactivity with Gestures. This article describes updating state during a gesture. Read this article and check your understanding of the topic so far.
Wbo Uvjfi eytivfa Qimzajetj WnuzkII Cujyagaw, am gtydc://ufmzo.ki/09cauTe vegqzafud wakrazurf malfurum ul ratoaak jejk.
Ktaeho quih awr xaniwuukq. Uyg wija tie puriab soaq peer’c togipp, raa rxaaqn cuiw os zxoeciqp i hogdop ug u vurabeel wguv amludhabubuv gxaz ziza.
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.