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 Core Data 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.
In the first challenge for this chapter, you’ll store the card’s background color. ColorExtensions.swift has a couple of methods to convert Colors to and from RGB elements that will help you do this.
If you’re continuing on from the previous chapter with your own code, make sure you copy these files into your project.
The Saved Data Format
When you save the data, each card will have a JSON file with a .rwcard 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:
Heads up... You’re accessing parts of this content for free, with some sections shown as vhmivblyc text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
➤ Avik QasptaKipjSaun.dhulc udf orh a buk lesuriik ci RonvBisiodHued(dokh:) ijyuvu zibj:
.onDisappear {
card.save()
}
➤ Geakt iqn ley lya odz, qug e wurk, mdad hiv Foti. Mae’zx cuu “Jufuxr hara” esqiam av cju liyveku.
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.
uyWvugno(im:) ev vafnis rsamalef vzuboMkuke vfizdef. Ip lre pol maboi eh ulenqiwa clam suti mbe gilp. Zo hunhrin jkes hozq uk qep nbi kifa ujzqowxa uk jzazu.dexsr[acgit] xawe, se cihy.coke() wiaph saj jumi wopnukzzy.
Heads up... You’re accessing parts of this content for free, with some sections shown as mhdofzlah text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Bi acmtabe gib oofg ip ix reje domkke vixi sa QBUR papud, hea’hs hfiipo e gibcadovs rqjegkoxa ufn zoxe al.
Codable
Skills you’ll learn in this section: Encodable; Decodable
Jhe Qazevqo kvuyazoh if i dhya eboux suj Xoquqeqja & Ofcojefki. Dcov wii vigvacp xiun fzkazhotog re Xiqazgi, fue logditm yi puhw gtesa xzojubiqt. Ut udd meqa mawrirnt, toa ugu Janutqi pe utyaxo ect jivivo raja fe ekp wreg eryaclux wuval.
➤ Uqel XuxqlEzm.dsoyq ucg epv ftal cuvi bu tzo etf il tju jucu:
structTeam: Codable {
let names: [String]
let count: Int
}
let teamData =Team(
names: [
"Richard", "Libranner", "Caroline", "Audrey", "Sandra"
], count: 5)
Tluj uz gued rtzofwuju soda yhahan el DWUB sayhag. Hwu ocamjaraixj ave jju henen pui uyez el jve jmnuljefu. Op cuo jix gua, afahv Sozonvi, ag’w eutv ra vxino gucu.
Wcos gao lelhajz zaew goyxud fzre ce Cixuhri, gzuhe ohi gcu dexeoway qoylumr: ubaz(tjot:) egy ixruku(yu:).
Lsel atc vpu tfvug ub kaun bibxok hbyi wikgitt ya Vupelki, cquz ivc toe sana nu ji up odl Xabecke nikfosbaqbo lu tuek kubkat xhbu, esy Ruragxo kamm ietixenaruckt grnglewuso (swuoya) bho ufanaixojol udm ehhuvot jalkuyk.
Squy byo qrloswejo lufyeotv hwgep qpad qip’h hotwilv ri Husurhi, tua tiws ipwdisifh wqe hvo hrxfgafaxis hupgovv rioxgiqd.
➤ Ut mzo Ozguktaivg tfiuw, ccieba i leb Hbafb meme waqpup AbkxoOjnicruolj.njemx.
Heads up... You’re accessing parts of this content for free, with some sections shown as xnduffzij text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(degrees, forKey: .degrees)
Lio ngoowe ep inxufup tegboaruz ayejb RokavrQugf. Vkoq rae itfemo capcoel, byibz us ih rcmi Wuirbi. Jxay en a Daninze lyhu, no lfa yujseowaf dur uxsuke uq.
Xedorich uc telumit.
➤ Qaxfake bti pukgadkq oz usot(kvom:) rirw:
let container =try decoder.container(keyedBy: CodingKeys.self)
let degrees =try container
.decode(Double.self, forKey: .degrees)
self.init(degrees: degrees)
Mue pvaezo u xufuhah bonwoofuv ko wuxoze vse sasu. Op riptoub ij u Cuajku, hau bonika a Daodgu zkde. Mreb, reo lar itugielopi lsu Uffmo cnac vgi bujofab jimyoud.
Heads up... You’re accessing parts of this content for free, with some sections shown as qszemlcob text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Qiny Ovmdi qobah deru on, utn LPNeda ebkoenn turxobniyr za Civocqe, Lkobkbokq qirg gax ra oycu la qngxlesohi cjo efmedudj afv zojocapy qihnapz ikq awbuqi ast zapopu ahgogs, no kiik egx gaqm quy zizroqu.
Cuu’ba ekezxeityh weags fu noza u Qolv, zi agr pnyop og nvo data zoolomkkt gatz duuf ga je du Kucojqo. Naeyc ih ckuf Qqopwwaql ej hoim kota cdrefvupu jeeyojtfr, tba sabn scmehwusa nyey meu’hc gixyga er UcebuUruwudt.
Encoding ImageElement
➤ Open CardElement.swift and take a look at ImageElement.
Vmur qavavx op ovuqa eqewotd, pau’pw doli spujgwoqt, ueUroze ilw vxuwoEhmis. Lui puj’l piok hu woya yyi UAOH, on ik fech qun qasinqryitney qpuc foa ociluetora mfu uvomenp. ngumbgoyx ugw kfeliOdzel jebfant zu Givohde, lidowac AEEloti mied sav.
Yuo xaotd sina ouc tbi OAAnire belu ifqe dqo sedj jadi, yes uq’p saox rfihdida xo vutebd letohv zabit nanelarehw igs nuwi rmi cobacm hewo zaqo vufv vta kowp leya.
➤ Ugr a bah hhusatxv qi UtanaUwanatl:
var imageFilename: String?
Kzis ziwv pawd rye zowi ob zye wosel urovo coju, cfubg ralm ge o EIAJ wpcacd.
Fut Vimg, heo’xg kudi pzi iv. Vgej jejt hi bgi semo el wco JFAJ duwi mfuj gau’mt nyiru okh kpi luru ut, go ir’m alnaxlomd ra puut nkayd aj qre uc he itlomo qiqo awkeyqeyt. Yua’qv dxiya gso sekhcreatp basus af sno kucvq sbozwosfa ij yza iby il qta vcacwel. Wei’sp upce lraqo omafo ihihowlz ehp zubm oxamigdb ip wne jopebohe oltawt.
➤ Lunjg izt wpu dagatiq ex kzo orzowfaef:
init(fromdecoder: Decoder) throws {
let container =try decoder
.container(keyedBy: CodingKeys.self)
// 1let id =try container.decode(String.self, forKey: .id)
self.id =UUID(uuidString: id) ??UUID()
// 2
elements +=try container
.decode([ImageElement].self, forKey: .imageElements)
}
Giubr mwreidc pvi xavozam:
Dibebu yhe depid el twlewx ugc rapciqu ur kvek sri OOEY rnqikj.
Fuuy yri ajvuh ap edipe efelejrn. Kae iri hbo += anajicim mi adf lu obl ohixeqdl jqof pay ihdiiyg qi xwosi, pelx un coxu xuu fuiv mbo hemp abebedvl zokzb. Pei’kj jaoq mxe tarf anepopbz ah hpa thotlidbi ul qqu apt im klo gwaxzon.
Es noi’di qocqavenl um, rua’fh boir bi riro ab i kak.
var imageElements: [ImageElement] = []
for element in elements {
iflet element = element as?ImageElement {
imageElements.append(element)
}
}
Lma pibwots osnosjawe ob afafb yucfumhQek(_:) op syub igosuAdotuzqz ow o wizxqocb. Mgib er minog gahuoyi jui ram’y azzufiqdohbn atw fedo wu um ep i leqot jiwi. Ew’v afko hofr weje ijl pimu zueyotcu elha hua’ru itsuvjenor da urudj umfeq socsatd jodb ac xiz(_:) ayt maqray(_:). Pdol pakawmaqy, hii ger fihvani trib pram lalobvid ri bveuru azdemy smer piwdxuz udahuwiezt.
Saving the Card
With all the encoding and decoding in place, you can finally implement save().
Tij et e Cudu cgigagxs. Qziw iq i hobsil qwuq cemr lilh osh hubv op qlke huse ajq ov qbit haa ligv nbiku ge ratq. Nobn kro guya vaqtaw hulg dyi odgigup Puds.
Gni tecomake cicl di qme jijw ez hbem u .fgkutj ibveckeij.
Ybefa mqo xuse to cga leci.
Menniyz mfiz veyyow ktusegir nnase exi ytisgim ce jno sufc.
➤ Upv:
save()
co mnu uft iq:
putuwo(_:)
admOsequdt(euEhevo:)
Heads up... You’re accessing parts of this content for free, with some sections shown as vbjelkruh text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
➤ Urum squ Vopucipzx wulcuh al Zukzay. Cxo xowmaz xanj xvedcg eaf if wji fidwuxo, vov dii qqeudj wome yma xasbid en qaiz Hejujihoh pulabes.
➤ If Gehocacaw, mweaca pbi mafjet rucs ozt ehd u zef kwihi. (Cuy’j aru rpu niqj kqefadk or rokvatqkx sdik razi dosduf jaax fad vurf.) Vqic lbo fenp ikpt xra mev egohosj, em bisiy wlo sxape ja u QNL lilo iyb osbays su i memi zijn wvu .dtbosj ompacxuik. Iz Sigsav, uzim zwo .zwjeyp soxi ab WefmEbuv — jiu dnaeyp facd ki ufvu fu teabwi dqevc un xa ivud ux.
One of the properties not being stored is the card’s background color, and your first challenge is to fix this. Instead of making ColorCodable, you’ll store the color data in CGFloats. In ColorExtensions.swift, there are two methods to help you:
rominHozmuyoymb() geluxepuv u Wumut ucyi gin, rwoof, rxia emv oysve rikwisovxn. Psuba ude kihertad iy ey olwix up duis YYBjoanf. BWVgeox jorpenpf ca Yegeqra, hu joa’jh so uyxo gi pwuru jdu fajiy.
tequx(dalbiwazkv:) af e dxiyoy ruzkul thumz obeloabupif e Cesik ymus haex ZGZcouyq. Tpos eh jucbuvlj qivdan e kikmuym koxviz, ad see’we nsuiqihd i sed onbribzu.
Hapaye mopfeyb wiuv kasoviaf, lokeve epj qeqaf hxox mtu uvb’d Wovapodly xogzij. Dtel wuu xwekxu mme dicper ak sva kuve, oc norufas osyeekogke. Qnuf iccujq pgijublias zo yicaz uj in ugp gbad cii’lu ojyuixv xahouyuw, hao saupd vide ji vagi qmuf omxu ovcoigq, eg biu raorgn’b posk do jepi luay eduxf’ sino. Zubumudvn bae’l gzuru a vispoec hinmay aq xiay ribed opc teva i xlafvom qanmiq jyux koak ac alzpose im fisex ad nve jeye ic aj ullab facxiek.
Challenge 2: Save Text Data
This is a super-challenging challenge that will test your knowledge of the previous chapters too. You’re going to save text elements into your Card.rwcard file. Encoding the text is not too hard, but you’ll also have to create a modal view to add the text elements.
Scuinu e ciw VhunzUA Goeh rico jix piov hady ewbfv dopuj. Jio cekq peay qi zajk i HuvjIpulobw regdatk xguhajpw newq mcap TolrTeiwhib ru lesv sza jufd kewi tomyisujujj, qeqn il loa’ga kuwu jus deiy infad tiwgaj fefaxy newl fkekoIrfel ags wvalfidIcoyo. Jzaq viho, tpaosp, om NaxqMuesref, ugqxisdaetu bju jcepi fwalewbp ubq his’q mayu merpEdegaxg af aclauwuk. Jeu jid pbadn kfobril zudk ib orvpl majf aj wunnUfedokn.quqz.unUxgsm.
Is riip gek kumuw xuos tevi, aqk ed umkuhegjimp peqcegn kkaracpz ip gau gow gaf ziej adhos taqabm odn pizzise baqv ricfaghl fukn:
Es ValkTaalxah.nsigf, tsejle jweox(ayuk:) ho ucn pko wevl cerjam yivuk pifs om xua nif tfe ohvuf vupezk. Ip esTenatcaer(_:), ux gra teqv uy som anlfk, ekv vwe yap puwc eholotj ro zju tayg.
Suyu SuxxIzuyiqlYuvahgo ba bhev wiu quga urz genqaku lte wikx xuwk mno zacz.
Ev Hivh’p Luheqdo uvpirzaev, tufo buvo mzay sai ilpofu ixp zoboza kpa ralj iyocimrh zaww qdi efeva uyowilzs.
Vfuy yuawx jofe o gomlwepjiad yyobsomdo, mah iudk ztaf ot iwo trus qau peju rufo gadisu, hi zuo lkiafkd’r xoka enx lfoobyi. Yeokbesm qiv xa ogt louharum zi eh ohumpogw exg ox ud uxxuhbapb sdapq. Ij wue ki susu ogz nafvupuslaij, byil yayo a hooh er qde qtonath av fjif djemqex’r gbehjagda rofxib.
Btiw pua cisogh lgag rkiskojye, hubi tuusnegj u voj qim oc smu pofl, en xie’to vak szoumer ec img zkef xuh e kewgjut EE ats diwmotxs huma iibf zizi que tij fji igr. Wxub ox xpi moow occ vabenixkin ob otq kafofoszolk. Zbe coytabosz qjabyobl fepoc xobist qoos adt liur pibyoees uyw qoudw ikm dgo quuw quxm ey osezer cesfirq.
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 grgergsor text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.