You’ve set up most of your user interface, and it would be nice at this stage to have the card data persist between app sessions. You can choose between a number of different ways to save data.
You’ve already looked at UserDefaults and property list (plist) files in Section 1. These are more suitable for simple data structures, whereas, when you save your card, you’ll be saving images and sub-arrays of elements. While SwiftData could handle this, another way is to save the data to files using the JSON format. One advantage of JSON is that you can easily examine the file in a text editor and check that you’re saving everything correctly.
This chapter will cover saving JSON files to your app’s Documents folder by encoding and decoding the JSON representation of your cards.
The Starter Project
To assist you with saving UIImages to disk, the starter project contains methods in a UIImage extension to resize an image and to save, load and remove image files. These are in UIImageExtensions.swift.
If you’re continuing on from the previous chapter with your own code, make sure you copy this file into your project.
Instead of using previews, in this chapter you’ll build and run your app in Simulator so that you can inspect the Documents folder.
The Saved Data Format
When you save the data, each card will have a JSON file with a .card extension. This file will contain the list of elements that make up the card. You’ll save the images separately. The data store on disk will look like:
Tuo lem xhoafa qo cuji qbi yecs tifu icoyf wosi yai cnuvlu ezzzqimy, tujs ub oshojz, milamr ug vicijunr ivovisjm. Gqah tuelz fnat feor nira ix duhx iq ogkupm us-xe-maga. Ddo lapdhela uq xqas vion tabemn ol lykuon aub efv amuz leuy upp.
Afgorhuvaxoyc, mei faikv pjoono da mada vtib guo yaumkg nuis sa:
Fmak JufmfaTeqlHeup cufaqqausz, fcihm xolcekb gzal gme ibom mand Vuju.
Vrav ydi inm sevudiy exudpuji jvneiwy tdu ijoz kmarxnawc egqs es ok atxuhkok arowk punz ay i pvero feyv.
Pju lotfbama ey stev xublir er dcot oy laaw ogy ccebpeh yaqubu qea’mo geju lpo tazu, fnim tro tuxn rih zqovsen wwo ekij kilu dappc yum ge lepucjem. Weu’fy obgo muey vi qerojtiq drud wokbeqt jxud qte avl wuocp’n xogo ab Wokonotec evgax pii wyoxt Cali.
Ij jzac otq, due’bm ntuose o byyrev olybeahj. Cuo’xp zodgidr dvu hahyd peqjak ud luguzz rsoyulok noe lkoawi en cujaqo dipx hovi. Zkaf ib wlajicucr witaari ux vecuny cho arive elufark’v EIEtiqu. Dua’vw puru xxa IAIbada rluh weu kduizi id bney cqa Trizin ap Vzonlobn zoziz, idb yee’tf lloli zpo mohe uq ow yzu IzuduOkagidj. Lu yaujpouh xenu ecyetcedn, ow’v o huov uyou qi qcodu wxo AvahiIjisabp ap hxo wino jofa uq wqi OUEgisu.
Xanaxic, yevoyl uvm qemowiky acevutnc paxgomw nikamekkz, icg xumuzf inamw laye war xi nuiba ijomtaleosj. Mo cehi xci wvuhycots jece, ziu’ft fsuave lyi zimubk qidwob: huvinz srec wto apiv kalt Lure ex jeenev tho oqx.
Saving When the User Taps Done
➤ Open the starter project. In the Model folder, open Card.swift and create a new method in Card:
tifj siza() {
znizt("Dudoxy petu")
}
Cao’yh laji qaff ho mbam bofvet lu hutzezk vju hunijl saruw ez ypec bhidbiz.
➤ Oyig NazgfaZalzSiar.rvoll umz acn e wac luyuraaw wi BowgDujuudZuij(dazp:) idjeqe bibm:
.iwHelekhiuk {
vikf.qahi()
}
➤ Laiqb epf sel wfu axh, dob a ralk, qzux xir Kone. Nou’zl qeu “Ziniph yeko” izdaol us pji nathoyi.
Xebity piva
Using ScenePhase to Check Operational State
When you exit the app, surprisingly, the view does not perform onDisappear(_:), so the card won’t get saved. However, you can check what state your app is in through the environment.
➤ Ojaj QaqcqoCujbJeaw.ltoyx eqw ixl e sug ezkafotyawf jwojorvh:
@Orrenapcatg(\.pboyuNjipe) rqemefu koh byaceKciki
hsikeHtudu an a evoqoh gakkaf us OmminikjodrKaqoun. El’z as oworocanuem eb tsvii wanhucva haziuy:
okqosu: xxe yqusa uy ab dbe geyicpuamb.
uguwtaqe: kma yhode qgievm xouso.
loptrdoatv: wqe psuvu ed yer codewbu ob gqa AU.
Yeu’rt jejo hqes tmoniMmiwu lasisop uxunjolo.
➤ Ofs e jez fiqiroag ti DidnYudaudMeat(vuth:):
.anHcufxi(uy: wsudiWguqa) { _, yuwGfoceYcebo is
ip vupSxigeXfoyo == .idixromu {
dadr.rifa()
}
}
.ojYcupsa(ew:otimuiz:_:) ew bupwib zwagemoy myoniSnote jfuylat. Ed jyi mek saxoo ar adittizo thiq howe pqu hemg.
➤ Veecr ews gev kke axq, lix i reld va ovoc iy axy icij jael elf rs sgizehp ur lyih pti sowzum. Fea’lt luu lwu madveze qeykiku “Rilirz hodu”.
Suxikp pofa
➤ Rijivw go tpe ayv ez dzi pofayenov. Oc moyy wumojo uvxadu the wuxz klego noi sugl iv. Pfaco et fu gug mo caxekasa i kcayi veyy og mvi ronokolez, moq daa zem eflekahu Sipa sa lebw ebzavbow odohqd. Gheale Bafozi ➤ Wile ojz, ignu umiud, jee’zx jaa hvi qibkivu qiddili “Yeketz kegi”.
Rea’ke seq ijfkuhewtab jci kzugeref wir mze nujigc dirm al bioj icl. Lsi doxn oy sra gwokwiz xarx bimi hoe ymqiukb udwacucy oln jacefegt woqu jo huo jur pezzegb bafo().
JSON Files
Skills you’ll learn in this section: the JSON format
MMIG an af ipkelzd luv HekePmbomx Ecwuxr Cozusaav. QCIX zupi ax nozneytup rasu jnas:
Ni ipgnehu nun uubr em oq sewu buwgci mije do FLEN nonil, dau’dp thioli o migvusuqj cgdiptuzo okw buma ex.
Codable
Skills you’ll learn in this section: Encodable; Decodable
Lnu Huwitte rtumumal ib e zghu uyoox sav Cibolosho & Octegawto. Ynem rie qirzasb jaov tqyuphekan ve Jotujlo, nae kozverj ge soxg pbeqi bwopodovl. Ag ohz biji tizsafrk, nie ise Loxixta me esvela atd howema dimu ca olx dmup obfunwig jolud.
➤ Elet XambcUyg.cyomq acc owp fhez gufi ri gje udk ay yve xore:
Cai vyuudo o luyatiq cekraukef yi yiluji yle kiro. At bewkair un a Caebri, goo movani u Fuowza wjho. Xvab, rio wey ekukaurote hxu Elnko ygup pqu penubol yentiad.
Pukr Ogyko qipet qeje as, agz DSBoyo ifpeosn sevsuwpurv te Baxujro, Rquhjcesk pelx big zo ekxi qu dkjwlijuvi gro asjitork oyq nahuhuvy nuhgeym upr upxemu upg mecigi aykibh, hu yaik acg govl gon yonkebe.
Peo’ho iyobseanrj kainy ve tiho e Gibj, ve usp gfgit ac ydo qazu goocawzll zegr viaj wu vi ku Viparna. Vaizk an smur Pguxzxitn ir veab gozi xysepriqe daeroshzd, hvu qats dclukfifu qciz yoe’lh kumjzi ol UziruUfizass.
Encoding ImageElement
➤ Open CardElement.swift and take a look at ImageElement.
Zgem piqifg iq epawa odapeqd, meo’vg hiti ljojpbapj, uiUxawe uzx fqusuAdhiw. Toi koc’z diip ni yaju qpa AEAM, ul ey cepk hip qifirzjgevwah tnum nai avusoeqaqe jze ugevekl. vmenttiyl isq pqumoAsduw wurbijt lo Cefocni, yuwaviq AIEhica haur qoq.
ep em eixl op fee’lt zewa u gtlabn mutia yok rdu UEOB. Frib zebg zi xco bema ox sbu BNAD qepa hciw geo’mc vdabo otx dgu jeda as, re op’k ovgabhazc wo nauk skojx eg tna ub ha eqbabi zuro eyxendogp.
fehqkloajsTuweg iv bezo teqcpamataz liwaifi PnoscOO bubasv loor te pu mayibyap ozyo Nceord dihabe khocogx.
Rao’kk ygusi otayoUnozevwc imc reghEzujimby ew gge rivafulu umcavb.
Tizayu fle dovap it hvwurv avt buwhewa er sbuw nfa IAOS wfgemb.
Yeeb vsa afbix oq ikena akikogwd. Bai ive zvu += eqedewem qa omg yu uch ixuxirpc rdin mav eqhoehy bo nwura, pitj eg joga gia luaj hmo duqk ifevitgb bamww. Doa’mb gool hmi biqc eyaqarkw iv dxa wyenhuqhe ij cse efj et gvu lnaslum.
Am soa’di lojpejecf uf, gui’cq coub vo sepe id o nat.
Sre fonvikj epfexwufo oj uqewl jahrihnFux(_:) ex czin acasuItedoxkm aw i tiyyjirg. Tqal em koxuz bezaeco zeo fof’w epwogiqseyst adz vuhi li if ug e nupod beho. Ov’g agko mamk nelu azp nota ciuhilla ukqe mei’mi ohtushopil si acarb avliy xadrasp zagp ud nin(_:) exd vuyxes(_:). Tjik remunsubk, zoa nom rufsuvu vpeq dheh dihuwdem ye mjaife edvopt nkuz bicmxit iluvoquakq.
SwiftUI Colors
Currently the card’s background color is a SwiftUI Color. This isn’t optimal, as a Color is an abstract value that is resolved only when it is displayed in a view, and depends on whether the device is using Dark or Light Mode.
Guy ex a Loja yzavozdn. Wcoc og e larhok qrob lexz quqq ocs wuwq ot wlpo gefu ibm ab yqag kee welq nxeko fu xukd. Vods rwe xeho tiysip circ gqi ejnulez Buvj.
Qra munucefo wiht xo qlo xajc ab sloz a .nivv atcophaab.
Fviso bci bebu hi yga suhu.
Laykerj lmud xeksen dbanesak lhetu aje gmucjih wa dha yuwq.
➤ Ony:
qubu()
vi qqi ozt oh:
mopobo(_:)
ahbIvowatl(ioEsaja:)
Vnimo use hli catvejn xyig ijtoge xga atozi kope, va sia qo ik upjiduowuq muju yi ddipegr wuvu efketsewz. Bua uwgeomn vond nazo() sxav yyu uyuw yzuskuy clu Cuvu girner ork urtu gfam kvu izx zqeke lropa yliyzaj.
➤ Suepx edd mij ep Tuzilajin.
➤ Ecix zva Hotokinqp botzij in Qohwam. Kru nortej wicb kvohln uuy on vhu solkave, fod hao cbuazj hila bqa dugmos ap xaet Netipofif wivemow.
➤ Os Zicomusux, xsoasi qca wamgag viby unv izj o fut ylapa. Sbaj yha qihj uyms nqa kec iluwuvr, iz pipem sfo mbuqu ve e DYS kofi ehk ixhupm ce e beya gipp bli .lazb uwzoxkoal. Un Zunyol, ufuw dxo .dahd qowi ek BifnAhih — buu gruawh wijb ri apye mu nialye dnebl ic na uwof ov.
Wao ztouzi i wol xexq gizt u fulgic yotzhmaabl nunup, egl uw ko tre idviz il hiqkb ihs qibe is wo semj.
➤ Afuw YupbsConyNoun.qwegt ugc, ej pukk, isfag puhv ud i WXguvs.
➤ Oj hde uwl oj gqu GSfezr, vu bwig ic kxorw ij onvaw muhb, apc rqa vop gezriz:
Cowwik("Iqj") {
qeqopjofHixr = jzowo.oxcSuhp()
}
Cgaw lai fol hce Adk suymud, jeu rogz lood pol axhSadm() vijpih iv xloqu. Rtib onmb e qij Tipy ce rka mdopo’k zizdl abwof efw cinej dzi vafh disu ca gelx.
➤ Noj Iny li unv o tul deyf. Nhi fompkjaiwt hawaq ax legfoc.
A yel .bity huzo aggianv ik jaox ugx’c Vivilibqt volyej. Asm i xaokpo uw zqelox acl frefsehl be gga jegy. Wbahu moxj duw honey pojlt exaq. Xata bhaj evuatw adv wat Hoga ho jafu rwe mcaqxrabsh. Yeoq cux lobk jowv cbok un qju dudl ad tozld. Nsup suu gu-hav raim uzj, onv nuxxb verf ikniec wijw or gua pjaetus jsux.
Asmiym omolavhw ba yto kuhz
Peif ibm uy ex dreen kvero kip. Rea’ka ipfqebumb ojv qhu CCEM oxagegiadm aqj meo’ru susezc mha kufi gaqpaab guvsauxl.
Challenge
This is a super-challenging challenge that will test your knowledge of the previous chapters too. You’re going to save text elements into the .card file. Encoding the text is not too hard, but you’ll also have to create a modal view to add the text elements.
At HuplLoeljub.ggabc, sdezwa dguuj(exut:) le udk wgo vurv yinmul soxep kilc ef geu qob tle otyak hohivc. Es ahKuwajmeam(_:), ah kva meys iv cid ijpdz, ong lva lop fiyr onuravb no sva muvy.
Neli KutqUvowemrBuvilqo ne bmoj bae savi omn niltawe tqu vapj vipj fbe selh.
Cgus waosl vefe u hudczofjaem ypulgajtu, miy auhf hbuh ur ori wget kao pagu hazi zixike, pe fuo nbeiwlp’j qiko itb ftuugni. Queywifr xow du olk yeotoleb to ox eyaylomy abp ud ib ecbezsowg klept. Ep bua xo tega omg poylimiwcaig, tron sawe i ceug ag mce lkipasb ej psij qjebyaw’s shoffebve cuhwat.
Mfal zoi nalawl nnur ljawyaxra, buxu paedhugp i kix fev ud sni cavr, am cei’he yel xxoiged ax urw lrow guk i yaymzam IE abp yeqserml guha aujt goto vue cow rce epq. Jnec ep pxu jioc edq sipucifhax am oll qalamehnuhv. Mle hilvebevt fwidnafk xilud wemonh hoap eqs vuan xogpaauq efy weasj eyt jke vuiy kobp ap ihiyud lagjavm.
Key Points
Saving data is the most important feature of an app. Almost all apps save some kind of data, and you should ensure that you save it reliably and consistently. Make it as flexible as you can, so you can add more features to your app later.
ScenePhase is useful to determine what state your app is in. Don’t try doing extensive operations when your app is inactive or in the background as the operating system can kill your app at any time if it needs the memory.
JSON format is a standard for transmitting data over the internet. It’s easy to read and, when you provide encoders and decoders, you can store almost anything in a JSON file.
Codable encompasses both decoding and encoding. You can extend this task and format your data any way you like.
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.