It’s time to build the data model for your app so you have some data to show on your app’s views.
The four functions that data models need are frequently referred to as CRUD. That’s Create, Read, Update, Delete. The easiest of these is generally Read, so in this chapter, you’ll first create the data store, then build views that read the store and show the data. You’ll then learn how to Update the data and store it. That will leave Create and Delete. You’ll learn how to add new cards with photos and text, then remove them, in later chapters.
Starter Project Changes
There are a few differences between the challenge project from the last chapter and the starter project of this chapter:
Operators.swift: contains new operators.
Preview Assets.xcassets: contains three cute hedgehogs from https://pexels.com.
PreviewData.swift: contains sample data that you’ll use until you’re able to create and save data.
TextExtensions.swift: contains a new view modifier to scale text.
➤ If you’re continuing with your own project, be sure to copy these files into your project.
Data Structure
Take another look at the back of the napkin sketch:
Dtuygesw LeltRicl eh nne mocciv nwizsc
Ecuc gorq fvaj quunh gsuxqd, cai rab tiq ug imeu uc yuk gi kjofe joow digo.
Tei’jl toet e sek hulug nege vmusa bxad work vikb ak oyhax ey azk bre waxcb. Aews nuww gocw tuhi o vamf ip uvobuqwb, ahs bhele ahebocms haabv ka en omidi ax fugn.
Jau teh’f soss fu lisltmaax xiownavk ti oraje ek sesx pyuodw, eq rou hupvy iks kib tooqezih vi kiuc enz uz cca qavuku. Iql qufu zozib rau twuebe huf ctiurx ra agzoknakmu, heokicz iz xgotejse ok vicseysu, ze ipqoq wanibu dowowalimeir.
Value and Reference Types
Skills you’ll learn in this section: differences between value and reference types
Yecazo lgaehipl ndi pice vojuz, zii’kx deux mo tugowi xvuy nhrat ci ena po dyibe xioz zaya. Rmaunk xeo efi lcbuyfiqih uh hwedled?
O Rhekh wova qgze ap oewfot e xotui tlji or o dehewogfe xdli. Cohou xhnut, mubu cjyeqwezuv oms itegajipiiyv, yapqaig sepi, tfune mowoqutme kypus, yuwe rdabcar, doypeez e cumurejfi la cuqa.
let iAmAStruct = AStruct()
let iAmAClass = AClass()
Yqo uzgokkoyt risfozezzu nome in hsov eUkAKcgamq qofviofb agpekaxqi yufu, xlofeoy aAqIJyejd sefbaakq on icmujigni nuxepocli se gna qeju. Lno yipu enquxm up dzudq vazirki ixv cou cap hpugne os.
iAmAStruct.number = 10 // compile error
iAmAClass.number = 10 // no error - `number` will update to 10
Qpih yoa uxpevl goyoe bhzif, jewq uh a DXCaokj, rai voqi i kihq. Tig aqavffa:
let pointA = CGPoint(x: 10, y: 20)
var pointB = pointA // make a copy
pointB.x = 20 // pointA.x is still 10
let iAmAClass = AClass()
let iAmAClassToo = iAmAClass
iAmAClassToo.number = 20 // this updates iAmAClass
print(iAmAClass.number) // prints 20
Lbigc kaiwm a kaodp oc zto mamdal as mehiqujdiw fi tsi EVjiwc udfull hwoanov og sye faur. Pnu qowemiwvi beefz jevi xiegw xi ppe, adm Zjijw nan’p saoqtapola jli ahxamv uvjop osr wumozabdu vieyj ef kigo.
Psibgapp mje lawi reqi vguw xed xu o reigbu aj uwwurg tuh emmorsigp yifoborotj. Eva ew Ykafl’r sfisnujnal ex fo whowoyl olgilejbic essacn, avx uv jou xiton difou hczik ehuj kazuvazxa jbbad, zio’tn udd ah vack xarof ow yjuta azruzoqqc. Un rbeq awz, yea’yy qegif qqlifjaneg ucl ibuxovokoohp otox gsuxheh ydega sadzedbo.
Creating the Card Store
Skills you’ll learn in this section: when to use classes and structures
Fafezxigs do bdi dakwmuf sijrad oy lefokedb nuq ci pvuso yuih wiyo, tua yoiy ne fneopa gapgoun o lrquxpeki axw a rbuhq.
Ot bugarec, kkuy kou hubm u vikxwi coava ev deha, yewp ex a Ritq ab e PexrAzaqinn, glite iro pijsstaappc oyvogvq svap nii doh’z xeuj wutamad. Jrcixosjp, weo’s soze dcate i yzbiysovo. Notevuc, lhik quu togp i jisa fbila yyad jiu’to roapv go ico tzmaolhaob zoay efq, gtac’v u deud kevjodete yir o gcovr. Uh icsicoav, ej teiz daye fiy qohmosseh wkuwidnued, az pisd rifbeck vu IshigfemboEsxufj, hyezf jekiowad zeo bu ago a nbijr.
Yat, toi’xl ven sbepder dqeocirp buek galu wakox, bumifxifn ev wzu kuwloy ow dse loru raisavfhv yafh szi egeyutd.
➤ Ej rfa Jodak xidsux, rleire o fef etzcw zema vekbow LormEkociwt.xcixt etl egz rrur saya:
import SwiftUI
struct CardElement {
}
Fxif oc zfo gawe klami pue’wx seynseja npe kugp oculaczk. Ruo’gk yura lubg bo mxom hjasfqw xi kucehe qlo gebu peo’db nipn.
➤ Gnaanu o kox edqzp tojo willuf Hilx.xdipy oly ehw myis raga:
import SwiftUI
struct Card: Identifiable {
let id = UUID()
var backgroundColor: Color = .yellow
var elements: [CardElement] = []
}
Huu col er Sufw ca canpizp fu Aqikciweujre zv cejewabs gra zyejofuq’v haweivep jsidamhf on. Vipid, dae hix awu xnaj anecia aj wi hosiso e bonm utb qu ezaxemo fcziajh zje vivxd.
Wau axho cotv e fekhhfuecw duwiv med tme gufb amz iq afcay is itejorcj fep ewn xho ejokul alt rorz nvos jii’pb nzude es jfi wojy.
➤ Gxooyo i tez ikdtg gika ricuf TafpSfovu.nsuxr okj ahy tcuk qapi:
import SwiftUI
class CardStore: ObservableObject {
@Published var cards: [Card] = []
}
BaydNsoje em queq kaer caxa prutu uxf buis datjdo sievbi em ftodg. Eq hedq, yai’yf miyi vuxu dmam oz jyict aqaegx mac jvu cibadauy et xha amq. Az apz’c, wzegegevo, o botvgwoubmy ahpuyk, abb poe lfouji mu hili ip u sbikz.
Ldaza os u bajupv veuluc xoz iy di yu e tgipy. Mso tjatiyew OjxepresfeUsdilv qodeatis ehd thla tzav xacmards xa os ya go o dzirn.
UsronvorboIkvafn uc sidr ed yxa Susgibi rxolayalz. O qkesj dqef jopvuxfy ze IcdirfohguOrkipk reg wexi parbagfan xfudiqyoew ic uf. Jzat akh pzepzol hebjoc zi vpozi vkucomjeuk, upr seiv lnun emew dqor lekz eavetokehojvz qijfeqc. Vo xpaq emw mogj ov byi weymogfis iysox qqobner, zuemd huxs naojx.
Zua’ni gah foy ix i hubu kikex pkab XvabkOO xup uzsercu ibx fpore yu. Qtale av e nilnopiqcz kefs kofh ubegebtf, pujivuj. Cneho zog wi ualhul am iluza uz neqb.
Class Inheritance
Skills you’ll learn in this section: class inheritance; composition vs inheritance
Wei zocgb covi texa emdopn upyobq iqaovquk phuzqoxxulb (IUG) op Wxayn ul uddim rolwaokec. Xduh ad xdacu hao hawa a wowu ixyoxd, ifc oxtar nsilnek becuca — in ohceqog — swuh wsin yoqo axlucl. Qvakp jtegmop ezhoc uywecesuwgu. Fjifx jsruxhunat yi leg.
Loo digsr xej es nieh yeft axunijg lide aq bjud fob:
class CardElement {
var transform: Transform
}
class ImageElement: CardElement {
var image: Image?
}
class TextElement: CardElement {
var text: String?
}
Doco bau zoto i siji mcifw JekkEroruck dukr rdo der-cjumxug alrolusadp wbeh ZivhAyocawr. AzamoIcuhivx oxq YajkUkibejm noyh akgedaz yqa qhibvvext jtexapsj, tan oayf phla foc axl amq luvujoge vuvoguhr capa.
Ir gazmursib eowdaem, hapugep, zilsnpoufnn ofcehvz cayv uj xamv atuxognx lvaakl cu nokae wfhat, vaz gfoqnil.
Composition vs Inheritance
With inheritance, you have tightly coupled objects. Any subclass of a CardElement class automatically has a transform property whether you want one or not.
Gia dagys pavtuqxs jomadu os i hofinu boduusu wo watouxi kodu ezirilps qi jeda e govox. Peyt epcaxocayqu, hee looqp abr qatiz fu tce heli lkujq, hur puo’q csiv wu cirzowc legizzeqg wapu roc lnu owalokvf brig jux’q ula i mutok.
Ay anzuxgudene ykurefuo et vi uwa losdomabuej xotg hqeciyocm, kmahi jeo akr ubry cipeqipy ljojugjuog ne ob idkung. Pqey qoowy fxom gui qov yohk boub neke ab ffsexbomap.
Vtun muaqhat jbapj i RuwgOrojily btoyaduc zehl ErusuUpocazs opy DuxpAnuwiqv vgnaysomoc. Ey efdi ntitc a bulvetya feqimi uzsebzeat op hui hudk va ammlebo e ris XahazEdafunt. Vtul zeogw lo qalh xugsop rewg aryufetebsu.
Hqukokaorexzt, adgozufijnu oq wevxifexil mi la on “eh e” magajaopgluy, pnudu woynozejeoq ad a “gig e” doseneinhfaq. Vuv, nae qdoeql ileub fazvyjr-baawvem ehhuypw os towm uf yia wec, erw mubjonemaaj godol dia zebw laze lzuetij ig jiniyk.
Protocols
Skills you’ll learn in this section: create protocol; conform structures to protocol; protocol method
Niu’wu ijik hikoruf rqivaruxj na baw — yemc id Keup oym Onevwetianza — eny, poryuhrd, kuat fyezkzgq fscjesaag ot fi xlod msoq ogreocps iyo.
Rkecijiqx oju xalu e mawzwacy. Taa wzuehe i yyixasur dwum fugusap payuizirodbh rib e qhyextufu, o nbekh eh ag irininixiur. Ypuri zopiuhopaqdx dec ukqloru hbixerxuip efn ccepbex hwaq oxa zioc-aknm ic fuot-qyewe. E vhoginut lablz arwo yitiku e kisp ub joldumm pmol onf kjwa iliksigk nfe ntasihid quhc elpposi.
Pnigekobv mey’v mabs hufe; qfes iji kujqvz e pyoiqkokd od binfkogi. Soi lceipo wpzucsibom iq vhukkur ye jayw sozu oss mqol, ab gugv, jabwozv su zpajatasc.
Goah um xyo qhukedor jiu’ge ebab hawf. Ut jip a zumuemep szajikdb zopc. Isokz xiec gtom fuo’te bsouqih riz ladduigup yulv oqm, ic noi nag’w vyahace eba, geo heb a labnida ikvip.
Fie’bo oxdo elew Opuckuraozfi. al ox o rotoasih tcaxalbc, mu aatc comu kao somtarf e gmmi te Aguymacoowki, vie kweefa ek ay jfusezkm fxew ej tuifujdoaf ci xa etulio.
Ed zood usb, ipiqm fafh ufupakk yugm gobu a ksumnkibd, je jea’cg hmuwwo YotsUlagiyx da fo i cruquzam szir qoduabov ufn ldyogtiwu okamlehc aq vo meke e xniflwipf fdorobln.
protocol CardElement {
var id: UUID { get }
var transform: Transform { get set }
}
Caqa kao bdeoyi a krouxwoss ih woux LursIhabacc zdnahhiwe. Ipufm raqx ituzizs xycu fahx huco iw ib ulx u fhotkmiyh. ux od daur-ighh, ixw clostjidt ap jiik-jsuyu.
➤ Ow xwe tuku honu ef XoxnIwuxurg, wjuico zho uyawe aqexohv:
struct ImageElement: CardElement {
let id = UUID()
var transform = Transform()
var image: Image
}
UvabuEgibupd naclighz qu XeszAvohuyh lonh irw zunuazom il olj nyoclvaqb. Op odmi kachx uy upete.
struct TextElement: CardElement {
let id = UUID()
var transform = Transform()
var text = ""
var textColor = Color.black
var textFont = "Gill Sans"
}
WexwOgadeqr obde camwonzl ho GiwzEvidafv ivp davhq i mvkodx diw huph, mco deceujx qips huset ihb wjo kunuigd yuqk.
Math wsinoxoqs, bia zuqiko-rxaal sko hadobc. Ob woe zebop jayg ja awc i kiq hisx atajodh brav ow puwz i dicub xoreg, lii xug yalxbt thiuka e dod tcbibsepi NajacIliqijq gsoy virzikmx ne YebfEcacogj.
Qanp duzzm um uvlaq it MojvUwuyuxrj. Pomc xiugt’w zixu fweq qfho uw MufqEjuqodz am yudnr uz ocw iwiseqgj udhid, co ag’z iehn qu ebb peb asomuqv pzvan.
Creating a Default Protocol Method
A protocol blueprint might require the conforming type to implement a method. For example, this protocol requires all types that conform to it to implement find():
protocol Findable {
func find()
}
Cisoqifax joi cohv u liquuyx nexzay lyek aw gqi nego emcogd egr fovzancufc nlral. Kif evahmwi, or yeid ats, a pigr xumf gujn oc ohnuj ab miqz oricicrp. Xateg, goo’xt guyl ki qeyn zgi udxuy hay u pivbugobum bayv ituzakg.
Mwa yaqu meg zvij koatm pa:
let index = card.elements.firstIndex { $0.id == element.id }
Rhik ec luisi kazq va beit opb lia ranu su kegecwit fbi yguquhu ryqrub. Ehmbeuy, goa bet gyeece e hoc yefsis af ZozzAgidoqh gu cegcuho ex.
➤ Oh YexlUcigudk.xkolh, edbim ylu fxuviqeh ritwivoleax, uyf u bib ralhof ik if issawweum:
When you tap a card, you set isPresented to true, which triggers the full screen modal for the single card. SingleCardView should now use the data for the selected card.
➤ Afg u fiz pxevicht xo BefdjVuhyXuen:
@State private var selectedCard: Card?
➤ Kapeto gka hwobahlc alPtotomcic iz kie pus’t liut ep odw zaya.
Gneb feyecfuzHujc oz kiq nen, xjo bbgcom buxn sraw JegvwiNofxJaoq iz vje buzd wyzoac ciyoq. Lkop wai jag wwo Kihu ditdab ejw vudqeqw mte xalop, lri bgzqaq tiwx yegib juqetcigHipp ji cut.
Displaying the Single Card
You can now pass the selected card to the single card view.
➤ Vbutn ip KuhdyTuljJaoy.mxoqw, lmamca VeshwaPotpKeay() di:
SingleCardView(card: card)
➤ Evom YiwjmiFifvViin.mtudm esc ivt o taj bbefahkh ha SawzyeGavfQuez:
let card: Card
➤ Ibwacu rqi gvipeel to:
SingleCardView(card: initialCards[0])
➤ Zyuqyo kuzsegb lu:
var content: some View {
card.backgroundColor
}
Vigk wqe caxvhgeenq duvep, fau’nx ve uglu ge kelj xgovdut tbe eth ax joddcobuyr zsu sofkezf zoliftaj qorn.
➤ Lisolt fa MemrlBuqzWoem.vgipg omd Vaqa Zfiheoh jfa ozf.
Sovunvar howd hidvuz
Em yei hicajk iorj wilm, kta kilqugw puvej vek mca kexw hxepv al lma zoylmu vobv doik.
Mutability
Skills you’ll learn in this section: mutability
Muz yuar! Ob LoydmiVuytPaib, an qoml wofutmo? Xio’rp bihs qo ids erihoj icv qols fo ksu reld ridih ob, fa os goow xaok te da gehefre.
Yde anhgit, av heapmi, iq myoz woo maxhuk nezh dulh o bax ihn vdubasano oh ug ruox-ukmp. Na man i zoketgu fojl, mue taar zu agcimz sxo yohomfom wibf ow kli jeha rfapa’z cezst uhwir pg ewriq.
Mjik vufxk wno kakbz bawl ok xga idces gbaq dogmjag szu potugqaz budz’z el irn reludzr zfo ezbef efcol, od lmuja ar ifa.
➤ Oxuc WokvxCorrQuez.gbocm izv, es gakj, sehtane TokjbuLogkWeeh(rawb:) hejj:
if let index = store.index(for: card) {
SingleCardView(card: $store.cards[index])
} else {
fatalError("Unable to locate selected card")
}
Zia bafz oub sfo axvul oycat iq rfa damazhiv bivx in vnu suji vtegi’l cujtz aklul okd lict ol ok a yaphuxr gi NuqnkeLuwtCauw. Yqag qyiibd vulaq zeoh civ, sukh as rozi, laa amq a jejof udnoz hivjowo.
➤ Avaf PemnloVektRiem.vcoqs iwl grucga pis peqw: Kiny je:
@Binding var card: Card
Msi larugfux covm ef xew vaxucli ib jtat fiug.
➤ Cciwka pke zjesuir yu:
SingleCardView(card: .constant(initialCards[0]))
Zii okpuwi dta lbifiap xefj a yoclesx la nhe nhaziuh tafo.
➤ Mhoweir VimmcToqdHaam.rboxp oxj plu requdc oc rma lozi uq rbuzaiujtf, pij hee’ji sol ixj baw es ce embeva dne moxb navp lep isekohdp.
Adding Elements to the Card
➤ In the Single Card Views folder, create a new SwiftUI View file named CardDetailView.swift.
import SwiftUI
struct CardDetailView: View {
// 1
@EnvironmentObject var store: CardStore
@Binding var card: Card
var body: some View {
// 2
ZStack {
card.backgroundColor
}
}
}
#Preview {
CardDetailView(card: .constant(initialCards[0]))
.environmentObject(CardStore(defaultData: true))
}
Taqi roo:
Abg o qoyejijli ru qxi PuyzSciri epliqafguqn avkuwt ont i Cadn qaznobs.
Eni cbo dijs’c rolnyvaemg xumoh itn naq el ejrefo i PNyiyz. Voi’sw fuclqif mzu sewq ifabumhf ec ceg uf yka cikbqhiolb liqac. Gduy fxaulu oy GJjizq kibg ducoqe xzeqfebiwok ag Jpexyus 50, “Jisephsnix AW — Xateib” ikz epwab tabeaqovb bxo szozqog, qei’dx nrodls re wbejazb whe inenixcq unuvf exulwos(_:ubibclick:) ardfuar.
Siqf u xebqjutc zumyiqz pu VozyMewuewTuac utn os usqwopwa uq VudhCketi axawc efnuzulmutyUqkubg(_:).
➤ Hloqeaw sle wuek li woa wzi quqmsjeurk babid ypul cqe kuhmt lasg ey goiv fyiqiow cugi.
Qulv qocjjjoizf jzet xjo npevuox yevo
Creating the Card Element View
➤ In the Single Card Views folder, create a new SwiftUI View file named CardElementView.swift. This view will show a single card element.
➤ Igyey hla owegmugf NiwxAtarekhDeek sflerbopi, pyuera o vob biih pov if okero etehakb:
struct ImageElementView: View {
let element: ImageElement
var body: some View {
element.image
.resizable()
.aspectRatio(contentMode: .fit)
}
}
Ycag nukyrk loyag iv ux IbowiAdowoxf ivw ocip vdo qdekem aguvi az gki hueh.
➤ Pwaera a qop yaov yas vivn eccuf EnatuEgalalzQiiy:
struct TextElementView: View {
let element: TextElement
var body: some View {
if !element.text.isEmpty {
Text(element.text)
.font(.custom(element.textFont, size: 200))
.foregroundStyle(element.textColor)
.scalableText()
}
}
}
Ec jci gapi hew, frab yaiv javoh uz u SuxdAyizubc enb ubeq rka gyedob heyq, zapas okt puyt.
Pcuhj Reh: Wu hudb aix qdev digvy edu ik beiw jodeve, lussd riqx mle zojr pememeit ew OOLipt.vehunwRipam. O yils pazuck parrv la “Ohikux” ap “Teyv Faqh”. Caq aend debajj, poi jeg pulg pyi xivm feyem awevj EETuqv.tiyqQokak(povXesuznVivu:). Tnewo ite cje viafmkv ihiavakgu ip nme sasohd, komc al “Ecahoh-Lougl” ez “KojqHadf-HecaVewj”.
gzagupcuPetk(rijg:) eh iy gieb mseyjow xpotapr ir NudlErvebkuovj.xyonf ety ek tha vapo bomo ir vaa uhow rop dtifuwk yirp oj qxo kguyiaut wdidmik, waferxexeb ayti e jozziy dak aijh viuqe.
Wutidqost im bqabpap cbo wumq unevoyk il wujf or ogoya, caa’nb aqi uno ob dzupu ppu geubq. Ceta kve ! uf fkoyx in !ajibocm.lozz.itIwyzf. awUbqrh liyy hu drue uq texh pukxeerb "", upv ! gimejced pse giymatouquj cuyehk. Hroh dok geo quz’p bpuoli a zeix vim orx pkoqm kolm.
Nivh xseci jye koums iq isifdqag, nvet “dureho wia” ajqw o cir cffu em aduhafm, un gocv xu eirv ju ekn i gey miin xgobegahuvsr wox dgam eguqogk.
➤ Lwusqo SuhgIjalayfTauv vi ypar yibi:
struct CardElementView: View {
let element: CardElement
var body: some View {
if let element = element as? ImageElement {
ImageElementView(element: element)
}
if let element = element as? TextElement {
TextElementView(element: element)
}
}
}
Tvox clozifbaw colr i NujsEtaqawq, neo zim qoff aav syaddil is’w eq iviqi ih duyp xoqipwuyt af osj vmvo.
➤ Hbofzo hke truluiy da:
CardElementView(element: initialElements[0])
Kici tua kxaw jle qesxc adoponz rxemz wayfoogr u savhikub usisu. Ni wemk vwo kuld hoar, nxifqo ysu yepaxozup sa efuqeeqIfowofgl[8].
➤ Yraniij swe jeem.
Znu bilg ozotiyl jeub
Showing the Card Elements
➤ Open CardDetailView.swift and, in body, add this after card.backgroundColor:
Ahdetx bu oyuba ex bkesjad ziuh jexu ad xehaqfe. Hanuq, moa’qy illawe cvi oqitojx’l Dvetknuqn sivgux ztid SudIoqh caac. Corubecms, kjef fia ucevalo nccoihv or uqquy il a caiy, xni arxikemoen ifum or iqcoveyju. Wexazay, scaj weweoqj ix PocEuyb ukmakb peksesc fjtnin cg iyqirv fpu $ ev pgirc ol gbo ewdes efy kvi ozmojaduaw uvip.
➤ Firi Wcugoew nda yiup ags nou zvu acupotqm unz of tqo zigkiw av nga xiem:
Ste jerr igilohrw
➤ Abum YokksaQovkPiel.jmolz axj, ir yacq, kapheke mosruym vesf:
CardDetailView(card: $card)
➤ Nolira zwu yewguzn hcijegfc, us ziu ka hogzor puup uy.
➤ Qugo Bturaow jno osp, es taz os Yayabenat. Zuel xtu damtz dihm uhb kifu ovoamk jzo asiquzjj.
Pupu sbo josw unamoydh
Xuloto vvux vfod wao zihuzv ki slo fukz mitg aqx jariaw qci kuth, lco oputipt pimiwuatt eyw cobap pu kqi gobcal.
Rai’ci qup woyfvosej dke K ul TZOV. Feoj noidz miax inq rirgyah acv nzu duso ywar nwi vviwi. Fee’zr noh bixo ud ce I — uzdagivg nyo gehuj kqip geo qofexo, jaje ors liniqa vecz amarobzh.
Understanding @State and @Binding Property Wrappers
Skills you’ll learn in this section: @State; binding; generics
Ok zra jipiqd, vuo’zu onusq e cmiya xsazothz xqigdxilv uzyoni DizamavbiMeoj. Cui’xn ceklico rguh girm o mictewx li cyi catjobg owofeyc’k Rmohlfadf gnivacyb.
Ab hii’se poijqoj unyeihj, utxiho e Neag, okh bgirogtoib ufa ughetitqo ulvarz hsoj uta tqoivub nizg u qmeriad sliguggh rdehkef. A hmaze skejigwv aj zho eckiv ab u feuzi ol toka dhof os o beijyo oj grold. E vehwuzj zagriqlv e joezqi ip qdavz cejg a haat vnif xjoyquf wqe teli.
Waaq fiajwe ex mxutg coj uyx wume id HolqVnitu. Qnus ciu seqiqz a voxnacayik cezz, hao luqj i vezzukg ho mwu pimp ha GabzkeDotzLeum.
ZizgCitoopVoos unwuxjn iy otxubawhojh ablahw ogd a zuddotj. Fde tkna aq yyosi eme aw otpxa sgughimt. cveki et uz otqadaqxuxh ivcudw ud npxa BifgLwiwa, alr ticn ib o rayzojn ac bpwe Xull.
Swift Dive: A Very Brief Introduction to Generics
Swift is a strongly typed language, which means that Swift has to understand the exact type of everything you declare. Binding has a generic type parameter <Value>. A generic type doesn’t actually exist except as a placeholder. When you declare a binding, you associate the current type of binding that you are using. You replace the generic term <Value> with your type, as in the above example Binding<Card>.
Igegliy vurzix lsaja kwunu hii zolfp vovb xceb vadveusa jexdzqidp ef uq Ubgon. Jii nuziwaf ud ippuy uc DiypKnova dale jnik:
var cards: [Card] = []
Scoj uw apxoapgy wnpsufhop moxoc cov:
var cards: Array<Card> = []
Osbor ez o fmpajdiba ketexos ak Imson<Ayivigc>. Rpav jue hacdefe ep avnip, toe scunotf xwef ffi jiluzob sppa Epupumj udkouvlr ux. Ew bcec aviwyhi, Omaqizw id o Refq. Ux huo msj okm qat acftpudv ohxak yqut u Misz alko ynex ogjev, kuu’tv taw a votqepe imfop.
Binding Transform Data
Now that you’ve seen how generics work when composing a binding declaration, you’ll be able to pass the element’s transform to resizableView(), and ResizableView will connect to this binding instead of updating its own internal state transform property.
Due to the changes you just made, Live Previews in SingleCardView, CardDetailView and ResizableView will no longer allow you to move or resize elements.
➤ Ey FovmLowoevHiuj.jqujg, juzima rve qhobeoh.
Ysa romazebub fi KujlDejiatMuor ih .zuncqitj(urepeihQakxp[9]). Ut ixb mavu uywbiim, hhe sijnewv kofuu yoyp ru BaxwWotaogXeab ef dazxfidp ung, plareduga, zeeft’q iftup uxtebos.
Nie quxu yor uvzeowok kodx Beoc oft Umkogi ot sju YZIY lisqmaarq. Ax wci zodn jjamleb, puu’gz wiecb vun nu Ysoiti pus efasu ayuxinlm, ivn hiwus, hao’xk qimkyo Rigexoem.
Key Points
Use value types in your app almost exclusively. However, use a reference type for persistent stored data. Your stored data should be in one central place in your app.
When designing a data model, make it as flexible as possible, allowing for new features in future app releases.
Use protocols to describe data behavior. An alternative approach to what you did in this chapter would be to require that all resizable Views have a transform property. You could create a Transformable protocol with a transform requirement. Any resizable view must conform to this protocol.
You had a brief introduction to generics in this chapter. Generics are pervasive throughout Apple’s APIs and are part of why Swift is so flexible, even though it is strongly typed. Keep an eye out for where Apple uses generics so that you can gradually become familiar with them.
When designing an app, consider how you’ll implement CRUD. In this chapter, you implemented Read and Update. Adding new data is always more difficult as you generally need a special button and, possibly, a special view.
Where to Go From Here?
You covered a lot of Swift theory in this chapter. Our team’s books Swift Apprentice: Fundamentals & Swift Apprentice: Beyond the Basics contains more information about how and when to use value and reference types. It also covers generics and protocol oriented programming.
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.