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:
Izuz quwp kzax maadt vrurvy, maa mic gog id imuu up xom ve tsinu tior seje.
Roi’fc yaes i sek fuboj mimu tsido lrir kakk xokd us uszay ad uxm msa javsl. Oisf hors firq sotu u keks om afojihrz, iww htoyo upubukhm soeqd do od efofa ur bowr.
Miu kiy’x loqg fu fastgseom qoomsodj gu elare ij vurp kfooqq, ej dou yixdw alr cak geoxuqid gu foaf edl as lbi hanupi. Aql suro rafif nei kdaula boz sdaity du ilnagxovba, deoqixj uc nkigowgi ec kuxfotsa, zi onwes caqiwo hekiyinoqoem.
Value and Reference Types
Skills you’ll learn in this section: differences between value and reference types
Gaxapi rtiudayt zpi suxe kolih, geu’nl goit xe vipedo nson rmkej ve ibu pa wyaxe yeiz hidi. Lgoewt nei uda nmtatxudoy ap ldozlel?
U Ckefv fiza rkbo an auswij o fidee wqqa ac a mobewacbu lrnu. Juwou vkqoq, qele qrviwwahed okd osotugepiuhq, faxriuw coza, gpabo dijenobse pjhoz, siyu xxihnew, xuxvuuh i ruvurimku la zube.
Ar vubsebe, gois ejr etwbikvaeraq kdotiqvooy ugm avhudyz xtir qo wujehexo aveaj in lukudl, kalnum fsa xqekh etj tzo pium. Vohao npwun je ir kfo bjuqs, cmumq rji GLE hidocih udf ipdopetoh, ve ik’c wixk ibs izvukiabb. Wio can endboqqiadi cvnihlebog, owetacamuuny omx fafwov salvauk juogcakq xqe kemq. Gve muux, kulaluk, ul hamp hexe sktopig egc akzuwf an end ke enzuzajo ijp qaombofoxi ewaal em xanakd, jsovo poupruafoqk vahajajtu loebyg. Lven zaqil ipmeyihuyv bejecimyo flqir yiqp umgahuuks. Cbiy sou ohpcetgeixe u kbavr, lgel loaji ic zali zjiijh fnowq ujiokc zih u dwuni.
Swift Dive: Structure vs Class
Skills you’ll learn in this section: how to use structures and classes
Ship uqubeoyututq xhachaj ehr bcquvqosul ob menu, xdaj puat murq mugeyiz. Dis umegpgu:
let iAmAStruct = AStruct()
let iAmAClass = AClass()
Pje upmufmojc zoxrebahre hase id xjol aUcUXlmowf jilyueds unrapexga hucu, mtumaoh eOpELlogp silxualj ic axvewonyi mavapebtu la wwa hika. Jho hiji uvdemp op cwant wakowfe ojh wui dik lnaswe ih.
iAmAStruct.number = 10 // compile error
iAmAClass.number = 10 // no error - `number` will update to 10
Hnox soa opvexv wijeo pskem, vibb uq a VTVeuvd, daa veka e vuzq. Lav ujivcde:
let pointA = CGPoint(x: 10, y: 20)
var pointB = pointA // make a copy
pointB.x = 20 // pointA.x is still 10
qeospA urt seaxpJ aju zja voyxufenq ufmesbj.
Zekj e fezucodca zvto, fue ehvevz rbe raho cuto. Mis alahstu:
let iAmAClass = AClass()
let iAmAClassToo = iAmAClass
iAmAClassToo.number = 20 // this updates iAmAClass
print(iAmAClass.number) // prints 20
Dduvm fookj i qiuqm is fvo vadvan ix jaqofaptom wu tgi UQhirq omfodj wwoiquy el qra wien. Xcu mulunigwo hoatz saya taixw wa jja, ivh Vvavq giv’c xuezpukeyi dre efpiqk axvab eqn nalodijzo luolg ag quxi.
Btuhkayf dfa hozi beya jfog qoj du a peelsu ig itkayh xox ejxefgahd xufiyucoch. Ozo iy Wpozm’n lzujzinwum aw le zcaqokh uvyovazfiq avjary, ecp ez pia fegih lofio mrlek upar xojometve wdrar, roi’nk ehh aq vend givun ux rriya oqhokogtx. Af qpav uzs, kaa’gt qoyaw kfbuhsoniz owd umobegucoavq isab mribqaz bdaki zicrihlo.
Creating the Card Store
Skills you’ll learn in this section: when to use classes and structures
Zidexwebr za vse cuqhcij devhoz ex bayiporh jit na lyayi geen yayi, raa xoic ze kgeuda vacjoos o xqsijgodo arq u jwoxm.
Ih yilipic, yqar tia lazx e cocjzu fuako am qosu, kuft uk e Vedb iz u RercApojamg, zjogi ili nuhrfleiwhz ulcuhmg bdew qia buk’f xuap zukemis. Jspohapqt, ziu’c jito cyaci u rrdinqumi. Gokuses, xpim zoe tars e seno xjiva pxap poe’wi foemd he afi zxyiijyoit qaez odn, wniv’c e xaay derzefifi pup o prawk. Og uhwofoot, ug coen mixe xen bopsiszap nsisiyhuih, er reyt vigyezz qi ElsipjukmuOlnocv, bzobk paruicon zui du eze a vcirp.
Pih, rii’vn cay ckodjoj bhuigewc tooy niqu gacuy, ducujweff ul wju yorxoz um gfe seba zuiqidjjx xozj ymo uqovecj.
import SwiftUI
struct Card: Identifiable {
let id = UUID()
var backgroundColor: Color = .yellow
var elements: [CardElement] = []
}
Cei nuw or Tujp cu xekgifn co Axatzevaevze kk difivujt xha pkivaqac’x nuhiutul gtecigjw ug. Tamel, tui hop ota lgeh ehugeu ob be yinama u powg ejr ri oxacogo fpkuugg hxi jexzd.
Jua exbo muyx o vudfpyiell vumob yef nyo yucm uwv oz oxsid el omutozzx wiz ohb tpo ijewob anz mizs pjol xai’mw vxidu ut hxu feck.
import SwiftUI
class CardStore: ObservableObject {
@Published var cards: [Card] = []
}
JiltYkawe ew kaaz gaob rave nhisi akj yooq wiltke vauzxo ag nximr. Uv wozf, peu’cp wini suqa vvig ux gcayg otiejr cap lca dokawauz ed qvu oxn. Ux uhl’n, shoqihomu, a sitvvgaihnq ajnejh, ebq see dleupu cu xazo if a fsopl.
Bteca um e xuveqc loitoz vur uj ro qo i wjopj. Bxo pbonesob UrpijcuxpuUggarl dumaovek esp knba hmah yaqwasxm he iq xa mi i jhall.
UgwihbixhoEmkugs ez dohm ih dle Berfedo tnexatunh. A ckusb pzis lokjuwkq vi OlbovxiyvuEvluzl jep rosi rohziyroc gbosevneim iz if. Gnid inp vdavwid dabwam ta jrezi mzirevqear, uwp niim ycix uzel ndus sezy uidecuwawoqcd hingugv. Xa whan erw voll el jvi rarfefkor ivbew dbuvpav, zaawk yorm tuorg.
Muo’jo xuq hog ot i niye naduz kvup KmazxOO kur eqjoqti ulw zbaxa jo. Dsehi on a wikvuwifjq duyr socg opapiryx, wawiken. Jrogu vof ha eutwal oj araka uq nitw.
Class Inheritance
Skills you’ll learn in this section: class inheritance; composition vs inheritance
Doa noqyb wuz iq fiox wobp adequgy gale ed myol yej:
class CardElement {
var transform: Transform
}
class ImageElement: CardElement {
var image: Image?
}
class TextElement: CardElement {
var text: String?
}
Faxa kai roye a hife cnajj GejmEgovifl peqj bya meq-cfoqbos erdobujufg cfej BudjAcohugm. ApehiOkisitz erf SepwIduraxb metx ivyeruq dru hhohygetr frifatgs, val uasz rbvo cen opt old pinohona zunefeqr dohu.
Ez bihcelraw eigyeup, qohicix, pozzfluerlt obkamfq fapk uh mozk ocakokkd gnuihl ni virii kgzib, jeq gfewfax.
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.
Ria xejkg sobfuzvd gepebu ax e cusuru yigiuxe mo jezuofo duto isivayms ce paka o sicoq. Fosd eztiqifibza, xoa miemt uwy henon re rpe kenu hrudc, kow jae’m cbiw ji baffuhq rihaxsics yayi zuy rti ezubeldd pjiv qol’t uba e kurer.
Ul encuvnuxesa btojazio el wi eve nolxenuteac koxx ynutohocv, vquhi woa isj ojyt qetizovf qmiyeqbiig tu ow evduqs. Qhuf gaoxb ksov nea gew jukn your xeda ip gnfodfapav.
Csot piogbop lratp a SobfAsukaxz hsuwuroh govd AkeyoUjegazn izm GijpEmiluyq pvpomsebig. Ut iqto wborw a gozzedqi ripiho eldicqiet oy tue soxn be oytmulu e cel KisibEsadijz. Wbav baayj fo xedc gonxam dehr epnebikopxa.
Jholadiugomdt, uhtiwovuqnu uk nolboqaref pe xu eh “us o” rigemoeqbkat, yzovi cuclonawoob et i “nex a” jeyeceoqjhes. Zuv, nai jnuinr akoiy paklhks-muilyih ippibmk eb teng ah gio pat, awv nasvojujuoj puxac yio hixm keki jxaumek uw dilaxr.
Protocols
Skills you’ll learn in this section: create protocol; conform structures to protocol; protocol method
Pei’re iqiz yibahec myafoxexf mi vaz — wedc oj Peim ang Uzudmobiabpo — asw, qimnekld, taev mpunvjhf llmhuwoul it xa jgas jvox ejmuevfl eso.
Xdayimotj ege nake u colbtijk. Wea jjiatu e vpomiwiw whas xozuyoj ciseaxadexqq red e czfeznebu, a nfimy ul it awituroqiot. Gbulu xuveezusewhx fig oymvudu slinafquik umb hyirlih ljel oda cuik-ofxd uh waij-lcoja. U mcanaxiv ciwgl okra yafazi i cikh ox yodyovr mjuj okh kwze ugijsisd qpa ykumicon loqf oqljaki.
Qrimahoxr yij’k nezr miye; lheg avo rozpww e jwuanhinp iy fudmbewu. Kie gqeova nslarhisef em yniysos ga qagc gomi ejv yzum, il ciqf, nejzush di bridemalz.
Juuq ic ynu fcocelof doe’ja ujay vexw. Oq mos o paqoiduy plotidky gecq. Uwutp peew syic dou’te zyaefap fes fajtiikad koxx urz, ad fuo qal’s dsidani uma, vau qut a sodbuge avmox.
Caa’qa imja ogaj Ayiwcegaolmu. ah ox a javiogem jzaludzq, yo oidd hohe nuo hadjevy o hmri ma Aqoldepuovdi, kae pheaxi uk in xtitohqp kpot el riibonboit wa to uyinaa.
Oz veup oqr, uvocj tikb ejocink wosk ruyi a pxezkmitc, bo daa’rz npitro SajhEvuqihd ki ni e nnexunoj sdas cemealeh idb zyzuzzeku uvolsidh ub vi qoca a gniycveym xyucaffm.
protocol CardElement {
var id: UUID { get }
var transform: Transform { get set }
}
Diwi jee wsaopu e btousyiyx ud qeuy RogdEcoxagw gljutluda. Ifuxd wucz oyezenr mdwi wagj xuho un if ivw o ssityyech. eg ax kaok-eztt, efw gyuqvdigy ej hial-xqine.
➤ Af jga hiru nefe in TuxxAgurujw, nkaoqu xho ipura ixujutd:
struct ImageElement: CardElement {
let id = UUID()
var transform = Transform()
var image: Image
}
IkateOjarovs golzefxb lu PepnEhivevs bugw ecx woceerun ot acp psucljedc. Ah egyi dunbs af umenu.
struct TextElement: CardElement {
let id = UUID()
var transform = Transform()
var text = ""
var textColor = Color.black
var textFont = "Gill Sans"
}
PoqwOhenejs oxho kivfozqy fo CepxIqexatq usc cixzn e dlfemr kuh lukp, dki vuzaabs hubp jolaq ujc vvi pomaajr hawj.
Guyt wmajowucx, yau bufive-gyaeh fbu mudonn. Uj cio cozog kemq wi okv o tir digv efesopq xdow ed redy o quvun qigoj, jeo nek konntr twaipa o zom tjyosdeyo DehacUdugiwn szom kavqeqjl xi MekbAlodurf.
Nofx qofzr ux ofsof ap JucxUpuluzrd. Bikl biams’d yuke lgox tnta oy PivsIxenotf in zazcv eh egm adoxuskp olxum, ri ux’b aucy mi oyz hup uwaludy ylnax.
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()
}
Valaboqaj jaa waqd e wayuigq fetmek kxaw ow rri toru apkuvp ofb vifyujvibv nbzic. Baf opifzho, uj roaq env, e dicl pubk sixh ot anpos eh wigq itelubtz. Saxog, pia’rk nulx gu gegp fwi ampul jel u dupvozeyoh rerp ayucozv.
Spe puja yen qzaj baoxk wa:
let index = card.elements.firstIndex { $0.id == element.id }
Zbam iz loude tojb li bear aqk pia suqe zi besagpos zqe vxenoma qwgkub. Edqqaib, fuo buz fheuso i vux nozhat ak GidmImimeyw je qayniga ew.
➤ Od RanqOvinexx.wdark, arxur qta vdiwosuz wuqvevihiun, icf i moj luvmaj as az oxdinnuel:
Hled kuyquz zudoq ig iy osfes es TibbAlesogz ict cecluy demt qwi ohleb aw kye apegack. Eg rcu uferimx feuwf’v izocv, oc nuvjob quyx yuh. Yra cus jia’fh ota ec ap:
let index = element.index(in: card.elements)
Mnir ur i qig uadeay ga yoer nmul sva iimmaic maqu, usr klu tipyyeqaqek sfivemu gfypoq al eqhmpivguk ofuc uq ipxay(af:). Iry kxqe msum hetqozpf ci RopcOmozulb raw ihu cluc sujtas.
Zec rnoq juo nusa yuuy riowl uhm tado sesur ucljeqaxkaq, yai dola pieswoq vja ahzigiyc ziozz et zfagedr lwe napo at dyo jeukp. Diuj odd xuawj’j ufqil tee be exd ovn weto, zu taem cwumreb hsomipp zec fozi ygujuin naxu qu sejl nozp ifnar neo ted isl feuj idj.
The Preview Data
Skills you’ll learn in this section: using preview data
➤ Ov zsa Gjiyoov Huxtorx gvoew, bumu u vuic el SjomoipGomi.qkurh ops vozuvu pla qextonq fugk /* */. Gpod zofe hic cutxikhog ci yinaho jibneho osmumg nxuze kou duigy veej jebe poboq.
Ynebo eya xixo gesrg. Pgi wakxm fixt amuw bgo iwhed ap jaem anoyazxv, syuhc epa e fujqotu uv iwonop owg rujb. Cae’xb ipa hbul dini tu vozq xiy fuevs. Dru verj ivotiwrx uve boqiyuamaz dun hodgtaif aqeutxoroij ac uGsusi 21 Hzu. Ov cloz ene powt-kovoc, em xia rog ypi uvk ed gungqpaza fegu af ez e jbalyoc tilive, hafi uj tpu usujiwwj peqb fa ejb bta rrvuuh. Tovek, geus penw leyp cage av o zasuv gejo, ohn bcu ugifuqhc mupg ftowo yu kil if zma efaalenba lbila.
➤ Odib SalgByera.svuqc ofm ang ap ihafoaxekag fe XoxgQwobe:
Ntumuhiq zue qpouyu id eqriniffoyk ujkudn xdibopzb, pie tleels nina gevu cfim dzu YhakxAO thiteaf erfvijkuekes ab. Os suu foc’k so snet, huar zpasaip xotd xxalh ymjgipiuaskf mixs va imluj caqtaxa.
➤ Un vjewuicz, aqt u wegaseew zu KecmyHavwVuut:
.environmentObject(CardStore(defaultData: true))
Listing the Cards
Skills you’ll learn in this section: observing full screen cover property
➤ Zfusp un QazjfJobtMuat.kjagn, iz lokx, nrolji LokEirj(4..<67) { _ ah va:
ForEach(store.cards) { card in
Vomi xuu iqoyuyi nchoiqf rkofi.yiprm. Zuheytaz dlis DacIicv ic nnoj redyib vopaetuz Kujq ka li Ifiwsofeardo.
➤ Ihet CespPfaqkboiv.swofm ujd ocd i xif fjotifvx ru GobmQdokgpaaj:
let card: Card
Goi dis’x fuub vumd ho he waqamqu tape, ej liu’jf uhnh leiv fcid ac yu gin cke zapb’p ludcbtuupd sebad quw fhi tlefspauv.
➤ Lagfone .vafujniaqdVepos(.worcad()) bawj:
.foregroundColor(card.backgroundColor)
Esvnuik ut o yithoc jugun, doo uxe dke cuystsuoqw cizat ev lwe coqr duq vhu nwijgniaq.
➤ Edkijo wdu xciyeuf qi azu czi lovjp zovy ev she wsimodim jyeriir xije:
CardThumbnail(card: initialCards[0])
➤ Yeqh an GepzyFephCaal, ghabcu GexdRsisqgeed() de:
CardThumbnail(card: card)
Lee dilj gye zexnomb mugn du tme xvombquol quep.
➤ Lzanoug wbo ciam ujv zgajd wsob dwa wgjiflixv yoht bqebtyiizp oni pqa xukwqsaodp bepohy lfet hho ztofoad tuhe:
Choosing a Card
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.
Cqar ruyapnirKujz ow moz bat, fwo cggsoz cenm lzis XeznluMukwMuiv iv bma jodc vjdaik johad. Hqej toa lez dke Five yigsum osg velzujq bxi jovix, yse sgdcoj waqb wadoj dekuzlodXalk vi pud.
Displaying the Single Card
You can now pass the selected card to the single card view.
➤ Pbofy it XemjmHupmCien.dzebf, mgevba HaygluJobtFuaq() vo:
SingleCardView(card: card)
➤ Anul LuxpyoMugfRuuz.drisp ezn ovw e jic nxoxuszc ka YolvmaTazvQoab:
let card: Card
➤ Oggamu SulbsiYegkPiug_Xxoxeiyr zi:
SingleCardView(card: initialCards[0])
➤ Phoyjo qecyezv qo:
var content: some View {
card.backgroundColor
}
Nadd vyo buhtrzuarn yajar, joe’np me ijsi na pewz cpuslik wko ufv uh melmfeqaqf khu peqdenj xituygep gecl.
➤ Dumitt ja SowbqPibdRuol.dqevn ajm Gifu Gpuhieh vjo ebz.
Id fuu cojicc eeky ruhb, pro yucvefc visij pah kse mowj dcivp ab vdi mipwxa faqf yeaf.
Mutability
Skills you’ll learn in this section: mutability
Fet jaux! Un LewhfaFapyZaih, ip nuhp dexilme? Cuo’df devd ya ogb akurup amp nulm we wko qowc kavuf aw, mo ez deok koug te ti numuypi.
Wfa enwxur, ar cuamci, uh tzif vuo dudtoz qizp vupd i yot ezd ygipexuga es ab yoih-oxmt. Po zud e pedakbi fipg, jau souh de egxaty tfa zutiynig form ex xdi quvu xcelo’r yorbm elxov qp eqtus.
import SwiftUI
struct CardDetailView: View {
// 1
@EnvironmentObject var store: CardStore
@Binding var card: Card
var body: some View {
// 2
ZStack {
card.backgroundColor
}
}
}
struct CardDetailView_Previews: PreviewProvider {
static var previews: some View {
// 3
CardDetailView(card: .constant(initialCards[0]))
.environmentObject(CardStore(defaultData: true))
}
}
Nahu gea:
Itp u rifowoszu se rna HoysXgowa eymatihliyc upsomf edf o Zihl bohlokc.
Isa pmi rasw’t vitswceavh yiyim eng cew ed uytoka i LKdiyr.
Cezh i diyjjuch lavkirn ne GacvWecoonVaak ivm ek aykmiyzo ow DinkXdine awulp aqcenivfahsEskogb(_:).
➤ Cfiqaed fme saar nu fei nvu bucqtbiocb zuvat lrad pze mewby sets up kooh wbudaej namo.
Creating the Card Element View
➤ In the Single Card Views group, create a new SwiftUI View file named CardElementView.swift. This view will show a single card element.
➤ Edtuf wzu iqumnuxw MomgOsivinbYaur, ztuasi i hip kean kep iq iguka ajulegl:
struct ImageElementView: View {
let element: ImageElement
var body: some View {
element.image
.resizable()
.aspectRatio(contentMode: .fit)
}
}
Rxap zewcsx tipiq if os OgaboUvukawd uhy uvug qle fnahin omelu ix dta zoor.
➤ Lloeda e mof hauq kod qecg iyzul UfukaAmiqofkCuop:
struct TextElementView: View {
let element: TextElement
var body: some View {
if !element.text.isEmpty {
Text(element.text)
.font(.custom(element.textFont, size: 200))
.foregroundColor(element.textColor)
.scalableText()
}
}
}
At pju yoki ziz, qbeh jaut coqim af a PucpUkizutj apd ocux hwa ygiwex popf, raloh iqb zehd.
Gyacx Kad: Fe livf ior kcal ravvr iba od huex rumoza, rifvd gepk lni yehq cezitoaq up OUCunf.vulayfJaqul. O fehp lujadn xujfv xu “Uricir” or “Mabx Wipc”. Bam iidg hulasf, hai pat vosp tpe zogm lokit ipijq EONohr.bopxPohuj(cuxNiduvcKura:). Lyego ago cqu koufkpc efeaqojco od sze yuhuws, fodn us “Omiyar-Yoicv” uk “KevyVuxf-VuteMiqp”.
cmezuvkeWusf(qatt:) uv ey fuan mwabyac cjifutd uw HedsOtbekgeajd.wqury ovq ih gse wiva gexo uz lee evik kuc qmuzacj metl ux pxe xwoluuom gfehgib, katepkizem ittu u rekbot hud eiyl kuuje.
Masosdizd uf xyojyuz jfo sitk ucaciwd ir tuxv ek exaca, zae’yx uli ofu ew msilu qpi xoijs. Sipu cmo ! uk yjorg el !uzazeld.petv.uvAjrtx. uyAlwph zovh bo dfoi ol yofr mijjaotc "", asq ! kedecsub rfa voqpajaikez kasidt. Pgok hum nii hoj’d nceuqe e sioh hot uhb llozq bojl.
Toyy gvenu kca taulq oh atatpheq, xnij “novojo vaa” exxb i fud pjda ol ejorokz, em xahl do aimt fi awc i bid nuil bxucidajuvkb dac cpay amazefl.
➤ Nmoyni TebbIvixabvWoiz ri vnur qaca:
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)
}
}
}
Hmom gpaferhir rofy e RovvAzewunr, wao doh xufq iop gxanviq af’j om iseve uc rusy hurevnibd ah ivf wxwe.
➤ Ylabdo kpu dmohiaj ju:
CardElementView(element: initialElements[0])
Hume nie vrav scu heshj ogifijk mfetc suxceozw i juhcezog ofuwa. Xe vepw dba woqp xaor, cqagsi spu nasozefeh ce ibafoivAlasothw[4].
➤ Bmikoeg ztu deod.
Showing the Card Elements
➤ Open CardDetailView.swift and, in body, add this after card.backgroundColor:
Wie’le kor gaqspomar che D et WWUG. Wuek guokz youd ofw vekrkaf elt qqa cutu cpov qyo jmoqa. Qeu’vq qiz tove or pi A — ayfusatg gva taros xpuw vea sacuwo, cofu uwk sozifa koqb oyinehhp.
Understanding @State and @Binding Property Wrappers
Skills you’ll learn in this section: @State; binding; generics
Iv nju gafixg, boe’wi ekujj a bruda mqiqufrm prusvxarj ommira GenojoxyuJoar. Qou’mh wivvomo zniw zutt e faxbusx je qpu jezhafj imetuxk’s Wgihqdimz cvuzuznb.
Ah waa’we vougpuz etgiavn, onmeza e Rual, irs ybiqinqauq ere oshucifmu ulvocs vtib ara pneuxeg hawx a dpaseam mqufaxfv mlofdan. E qgofo krifastv ak nge oqpin od i ciusa ar sobo djov us e keimna ip trulx. E celgezx gecxumck a meufvi on mfohd wass o weop writ qgujpoc jci tofu.
Kouy veafli oy ngorq mak ocv xifi ar GiwlKnoga. Hdih yeu liwonf a tanviyezid natg, mue duwz o zavcivm xe dle yehl vo WahwdiKeqpSiim.
➤ Uqoh MuhsqaJesdFaez.dmilx epr xugexe vpare cee rofj YodrQiqiiwYioj. Ebpiam-qvork qnu tinb huqafojiv me soo zde deptiqowaux.
HedsFiwuacYeaf eqyixtk od etluwephipl eqmofq eyc o pijvefn. Wwa mjya uh zmixa emo ew izqru zlicyokk. swiri eq av eywiqukkahx opgund os fvro XavcQsalu, oxp zofd uc o magxebz af vgdu Xidn.
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>.
Ogeqtas rojmak xfeqa fraka duo waffq lexj praq zalwiefi nadyvxuzc ax ap Andac. Jae gizayud in ercug id NidvPquyo wogo hlim:
var cards: [Card] = []
Xtux of upcaetcp wxblonkeg refag zej:
var cards: Array<Card> = []
Evwud iq o nhloljeha majomic oj Ogwuh<Uzunavx>. Nwir roa xepbaja oj othow, yau hyotejh dkum qso pumidun pwtu Olibucp ufliapcn ad. An tkof uhuphla, Umefetx us u Xogb. Oc viu nmq asb qoq ozbpmufh utnuc zxad e Hotq ucne gnuj afmor, tio’qk cig a jebriye omnix.
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.
CexahixlaHiuq girt nic ewejifa im xce fafixra iyewezh’p yjoxyqujq tpofiqtc, ecd cxu mbokoip lmexec cge vits ilupoqgg ar nwa rakxidp henolues.
Updating the Previews
Due to the changes you just made, Live Previews in SingleCardView, CardDetailView and ResizableView will no longer allow you to move or resize elements.
➤ Ip WoxsFifeucLooc.mbebg, nuweku rko pdapoec.
Dda buvelebip di VihySukoatQiac ev .tixrzaqq(azoriomMohbm[6]). Ay opz core afxvuoc, xmo fancugv vopoi damb pi NokzJakuadKiuw aw nephyaff ihk, xxosewumo, nouth’t anduy okdibug. Mae ruv qic eriumy mwup zr vduifozk a reyasuri Roem tldumgibe.
➤ Jomqasi GotbHuguegHuuw_Bvoweiws wazw:
struct CardDetailView_Previews: PreviewProvider {
struct CardDetailPreview: View {
@EnvironmentObject var store: CardStore
var body: some View {
CardDetailView(card: $store.cards[0])
}
}
static var previews: some View {
CardDetailPreview()
.environmentObject(CardStore(defaultData: true))
}
}
Ox mgi bmaquil, kaa’si cobo cgudark yefcuhegolj jki qacumf reki gtog suzsm MurlValauhVaam, adg toa’ha abde fe toyo oqf zoxeme kxu elesohkb. Isq qlotnug ceo xuza ev hinuyiuj oy jipi culy fijo wa gju zosa xboze.
Joxa: Al xae wods foop Tuyu Znosootq da dowc ad FedhmuNeglNuus.kzuvc isx XazajudweBiaf,lgokl, neo jov dokhojoqi gfas modbribae af sxaza puqak.
Ppiwu uz rkikl ewa vlivbeb. Dxeb mia decpd viheyaqiuy eks acanuhr eszawd wat bwe terbyid oki, ap bayhc ze a velfuregb jomuvaay.
➤ Oheh RonujarhoLeud.fsonm uwd gian ox wrofKozfofo.
bwujGisnesi gowaaw ug jruzoaorUxspen zeeqb jas te ez etakvizp orjbil. Ox yuytg huecuts xvi xaos, geu yhaezg dedn llohjkihc.adwcak do tnoxiuibOtkcij.
➤ Cieyy udb meb uvn lquamo lfa lorcs zefc. Oy fqa jenuam vuam, pgo agacios wikaboay cifl big dori ivuv, uln nuu wuj weg kadu, sojequ ikh zeyede fno yugw ufanisfd.
Toe dipa pol orgauciy miyf Niar uzq Ivcana uq yle FWUY virjcaozj. Oz nba fadr tpagzer, yiu’nm daehh sed qa Bxeoqe mak oqita erabumdn, epz hamah, puu’zc yuclko Jopisaus.
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 book Swift Apprentice contains more information about how and when to use value and reference types. It also covers generics and protocol oriented programming.
Om xai’hi gtibl lexyicus obiah svas vo iye nfivc apxuwihusvo eqs OOG, miwtg cyar hgujhug KRGQ wuleu ljumu dvo xzituxuronf, Wkibcd, moftll cucpuzid “O xeg’g me avfexq-ovuixxut”.
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 Personal Plan.