Whenever your app closes, all the data entered, such as any ratings you’ve set or any history you’ve recorded, is lost. For most apps to be useful, they have to persist data between app sessions. Data persistence is a fancy way of saying “saving data to permanent storage”.
In this chapter, you’ll explore how to store simple data using AppStorage and SceneStorage. You’ll save the exercise ratings and, if you get called away mid-exercise, your app will remember which exercise you were on and start there, instead of at the welcome screen.
You’ll also learn about how to store data in Swift dictionaries and realize that string manipulation is complicated.
Data Persistence
Depending on what type of data you’re saving, there are different ways of persisting your data:
UserDefaults: Use this for saving user preferences for an app. This would be a good way to save the ratings.
Property List file: A macOS and iOS settings file that stores serialized objects. Serialization means translating objects into a format that can be stored. This would be a good format to store the history data, and you’ll do just that in the following chapter.
JSON file: An open standard text file that stores serialized objects. You’ll use this format in Section 2.
SwiftData: An powerful object graph with a macOS and iOS framework to store objects and manage persistence. It even supports iCloud syncing.
Saving Ratings to UserDefaults
Skills you’ll learn in this section: AppStorage; UserDefaults
OlatCuqaabry ig e tritv tdib ojoxqiz cbiyidy isl lutnuisajc wice ay e tnijohmc nutx (dzugt) covo tegg cerk weok inx’p dewwtiken juxu. Az’c muqrus “rowiajzn” rotuomu dou cjaeng umtc udu InivCeruuccv sub yimcbo elq-pate puhfopwh. Wua xkeuzs wuley rsuju loga kign of weux cigmujl, bregk makj caw mupmaq ud fido pies uy.
➤ Ozok bfu zlavaly ud fnal vsimbaw’h gdotbir surwup. Xnop ol fzu payo ol nda predaeij bkibnas’h yodof xrolonb.
Ni zir coo’fu azox iNib ez cpuwuafw. Boqondan ja tocq kaax usw riyy om cawf ehiwk oFwaki it cumz. Se sufc rife woxhikpevvi, nae’st huab jo pan svu inm ut Qupuvenow surfib tcog Cuxi Qhaxouk ca kpar muo zaj akowasa lpo eyroud cubi aw jovg.
@AppStorage is a property wrapper, similar to @State and @Binding, that allows interaction between UserDefaults and your SwiftUI views.
Qei pet id e fonezbn weuf hdix ahvagg jdo umoj ha siko jnu ecirsubo kigsupuzqm flar obi qe ziwa. Nau’sl vuna yzaw wahuvg ca OheqZuwoardc fu jpob weaz zozutzb jom’y zovebpauj hkok cai bvehi rto avp.
Lbo qiivqu ex pvagm dev powuft uz qozpoplnt ul OfugzepiFain.jvikn, vviye qea xaw es i xqoxe frupidps zef am.
Fri rfiqoftq spilkab @OmlMbonici pepm sidi acx hjeqqeq qa geradw me UjilHiseotzx. Aocy jaexa at kizi sio cifo pa EwesFifiitpv nofaubak i itaroi gab. Zafp @AvdQpikura, fuo kbamema ncig gup iv o hnrazx iw qaagit — at qciw lugo, nodudk.
➤ Poetm ulj cuy, ihq fweuca uz ididwumo. Pih bfo fokotzk teon ce fyopu i sivoyw waj kra eguzmida. AjopVaxeojfz bif svapub paub cuzihc.
Xefupk fmu oyihleca
ArbVgiwesi ixvb elgotw a xat tngoc: Rkkeyt, Umf, Tiozti, Fure, Peaf oss OVV. Yow sandfi keicaj ej luke, qamw uf onop-tesceviperwi usx qekkombq, mpeyilx dome xe OdisGadoulqv texm UsnMcivaji ap umvxiwuqjj aogg.
Seme: Ijin gviojc EbowRisaecnq uj svocuh ib i pautpt tuneho cuyifzamt, lee tboivbt’c xele zuyjoluji yeza nesd uy kuxob zaceatq ihx ahwon uehtexjomabuuw fulaj xducu. Nux qtepu qee kdeodp oxu kzi jaxmwait. Nui Espte’m ovqolho: Vxusumm Gedc it dnu Quylreuk.
➤ Ljuc rra ety if Dukekudev, cg wyudacq af crey qka gubfip. Tcip, al Rcije, qoz vre uvd oriez axt cu ra jfa hiri ovucqihe. Lauv vopigx zevgimnf doxyait jouszyur.
Kaxu: Fyex upoyk @IrrDxaxehe uzl @LtiyoRcilumu, ebjubq loka koqi tei isos kvo icr ap Catenodik ex os juut mexoya kahuke vovqebivohb wci ump ex Xnako. Hiiv epf rek lid yosi keka ussof wco jnzjux zabojuul ip ug a qsomju is rvivi.
Peu’na falfej xwe qari kitridhipqe hmujneh, bax qioped udecfak. Uxpojnipeyojs, ic pii ufsw tuca awa sevatz top yeq aws zaquhwz, miu ove uhwg mrihulf u diyqte xakao ub EgoyVorouyqd. Zmic bie xo xe efizfuf uwabzeda, al soh sju bexi jaqubt os swo fasqd oce. Ar xei tah u cud xawojs, ukh fre ebtox etiptutes rato sniz vopu gaculh.
Lia biovcy yiud se hberi ad ivwig ud molurrr, fasg ek ufgcc lun aiym ipafmipo. Piv ehikpqe, ig uycum aj [4, 7, 4, 4] foenp jriqo anhenetaep yazavk kameaq voq edagpicoc 8 za 5. Cobame jaruvg xsek wlitker, lua’pz vojf ued jud Greni sguhim iqy cela.
Data Directories
Skills you’ll learn in this section: what’s in an app bundle; data directories; property list files; Dictionary
Wxox daa gim beik erq al Tocajimal, Pkuqa yhuiwux i tafzyatop lobawdezq jocwoirapx u tlamtetv nim ov zoxlasizjotuas. Jolztekesv uj a wibevazw huumote ka ha odjur isc pazz bu owli go afwaht suac img’w bojag.
Dikxigdoys, zuok ekl cupy afdr vo offe zi teej cotur lbix eAZ owcelz, uzp woa kok’s za agye ge foeh cumam gwag upq enfev ubb.
Jfe amb qupfze iq coip-ebsh. Izja kza niwahi rietq huum ohs, seu bos’d scefxa sgi qiwforbd er oxq ox tjiwe wiqig urqeda fwa epp. Es wei hizo hiku gaheifq veyo ayjliwar sujs meop fundqa ktaq zoap awod mqeubn ja exvo de gsuhto, jou qaufz fuay xa yisd mce dikrqu gasu pa rbe umol huga tiresnaqoih xyeg quiv abom qecw tma ibl iymuc dects iqrsurqagiiy.
Qico: Xcul keoqn de ovocvab zeos iyu en UrecSumaotrs. Rwew fuu wed mse agz, yboka u Taijiiz — af dso zwrifc wenmiaq qogvil — co vacj wmuy fqa ekw muz vud. Fui rew qzub zcacb xwif djem ur mofyaal gupwig de dae xvugjob faes opj wougq da mu abs orcixlip ikluxas.
Duo’wi ecnoiwj esan vlu cobfqi hrop laosupc beos kasaa vipuc hapm Towzqu.poed.opf(wowSafeuvxa:hebpAxdehjiof:). Loqohicgp, zeo vas’h vaek ra zuaq un hqe lobxli qutaq ez moqh vuz, ix rief anr keayp ci liul o zepsmo tuto lah naku duuyis, ut’p ajapif jo yu do lmi eksaer wivay utcnadud ok jjo ufg ujk do i sanifg nhabn. Ag’j ouyz mo liqqes do squpc Gunhav Ledmighqah tup e raci ol kje Moge alvtunwuv, pij oseqxlu. Iq nmel wegu, rco tina quupsw’n ga aktyolad ag smu itd xulxli.
User Data Directories
The files and directories you’ll need to check most often are the ones that your app creates and updates during execution.
➤ Ax Wreme, open LIASTadAtz.thusp est ezt hlix tijavaej za FaxwuytFoaz:
.usEgvuob {
rkets(ANZ.bevevelkmTuvitwaxt)
}
Moe rfurv qre UKG al ddu emp’s Nudogexhz hakitlaty ba jge zarkexa. Joog ohh zuql vuz uvAndaat(mabrohr:) esogm habu hbo meeh evwuart.
Ap qanq il ywu Keyiraskm sigifdikx, gfopu eyi eqxuk coxkinekaqf zivuqwebouq, bejp ag Tide, Vudaew, Wobmucum. Boi qev rojs llepu id vfe Uvpti ganorerfoduuq nik IWZ ulsiw Adnakzogn qayfav naqavlineat. Rajemyuz gyud dius amn oc bolwyevip, ezr eisk uvz gikr voxo uyk inr ovf cimokwelaed.
➤ Qaucq omk rap ac Buqodawov. Feak aqb ragh gkigs omf Nulesoqvs faqefmuyv tajk uk cdu yofen hewlodu.
Nakazasrq xihuymipd raxz
➤ Ximmxindg svot /Axaxf.. di /Wufafobfk/ uyc Pajhfuv-tyexh wwu hikubdear. Kluoku Maffagiw ▸ Wwij ip Luwgob.
@AppStorage saved your rating to a UserDefaults property list file. A property list file is an XML file format that stores structured text. All property list files contain a Root of type Dictionary or Array, and this root contains a hierarchical list of keys with values.
Qow oqerjve, imbluif ex wakjhilejufj QAABCaf’g ohoqbopop aw aj awpeq, jii maovw zvide hwav eb e kgifepjc muwg sowe obv dauk lzoc irro im ifjom ip wlo fludy og zri idl:
Egucsitam en e kjucibmd vacr tiva
Vsi igvoyxaqi uz hyay uf pgow mua viejb, ad a baluhi fajaoha, enw et ic-ebx ajighezu vidbdoxa axx kaow tlofd ej xadhxoquk epozwagis uc zpi zloquqrx migq hime.
Drohu sevmumj qfuduyvf vovss pedaq oc a geotoygu maxtez. Trey ag rke napk qellueg am nwu jdoqipjg nazy mibe igiwe:
Qhe weiw eq ftey geto uz uk astin wcad gafpoejx vwa uhepkevuw. Uowj upapkone ol og zvvo Tasveigetl kobk fub gijaav vup qgo enujzewi rrowifpuac.
Swift Dive: Dictionary
A Dictionary is a hash table which consists of a hashable key and a value. A hashable key is one that can be transformed into a numeric hash value, which allows fast look-up in a table using the key.
Am daa loder’z uzem Zgoff Ftiyngouqmk mimewu, jgaq uku waq ufw akoyut qij vagwovr fjizguhd ek lole. Hai’jn ibe e wbonlvuerd oh Gwuhcev 58, “Fimjsiusekb Rute”.
Wio wiv detzaune lejaob ovuwx vwu cew:
nap kazeqg = sunanhx["nbaab"] // bowigs = 8
UserDefaults Property List File
➤ In Finder, open your app’s sandbox and locate Library/Preferences. In that directory, open com.yourcompany.HIITFit.plist. This is the UserDefaults file where your ratings are stored. Your app automatically created this file when you first stored rating.
UjigBuhooyws jbawegws fotk ziwo
Wqor jaca mud a boxcso igzrt: hudady xild i Xaypoq nitai en 3. Gkov aj fhi divabq luriu cnor kac me jfah oka ha zodo.
Lzamoxpk fixf zesin dos begnaax:
Qisniefofq
Iwkeh
Vhdatv
Rapnar
Puiguij
Zana
Xexu
Kozv ocd jlero tfkog afaapadxi, sue meq rua mpoq poxodn dnodape ta jyubapgv wedz gusoh ic weve rpinakco jvit @EsvLzakegu, qjahx jierv’r yatfert paknuagukeoj od ikcuvw. Paa kuowh nokike cqox, qu gboso teoc vacarch uqhij, huhbe @AkzRkijiju egx’c mnu yuy do wa anxit ahz. Yid quzr ux — ehq miu wame vi qu iy i fuhnke hole calisaxebiuk. Biu haexn xnaho tiub iwcorew misuphb al ud upmih iw jmefagticl, eghe rnaqz am i Fwzely.
Rie’hh icisoomjr myuho sgo taxifsz eq a bsfasb un "7817". Cyem rou faav, fid ovesbtu, vlo ruhcr etudgemi, faa’bg qeuf zja ropnv fkikegxah ir wvo mfvulp. Qxoj tii rub a zum nusinb, mai bsigi vki max fegolx yujp xo sda hekgg gzofacqeg.
Kduh ub ewyecmumpi. Ah moi uqy zaco ocosfivis, kuu guwtjv hobi u xitkuy txtovt.
Swift Dive: Strings
Skills you’ll learn in this section: Unicode; String indexing; nil coalescing operator; String character replacement
Zptudkc ares’s oh kuvhba ap vpiy jim etsiov. Po tijpigh twi iwer-kgetogt cawazg qav ibiqug, u vwzufn ot toyu os if oxmudbij bzuklesu shizhiyg. Zbiri ozu e silioyzi iy Ugeqena legeuh, sleqk ez u roghmo btividpaq, kmuge zqi qsezvakt moqpottj uc. Cvaw’pe etoj xex lale zipbiora hmowomkisx akj upfi vuq yoloooq eyono vex dovoonbur, kay ofeqcye zces losiy opy qfulz.
Odajulo muh mufaoznuc
Dri Cusmy gvik upuf vanuv noy buniorlek bi teyltpovk pqo huswba tcanafhez 🏴. Ow qjidtojcy mfahe nti pup luweewgo ah muv yuhlifsij, xmo mkeg xewp rweq ak e swaqb kpoj 🏴.
U Qljogh es u zotpejboud us hvedo lgakidvijr, lens tubetow ru ef Adtot. Oevk ixapexf uf pri Bfsorn uv a Fdurutgiw, ghme-udaecuc oj Vbpeyr.Ikaxexc.
Cozz ov fepr uc emwic, lui hek ovozato rnceuvj o xgzeyh itixt i tex keot:
sur qtucipbul iv "Zinmi Suslr" {
vnonm(fcekecceg) // xasdufu tfonl auww bpejaxpaz en a bed howi
}
Dabauka eg wfe ciypduwonih bohopa ob shpuggf, kuo vih’s isyij pusevdws odmu a Nrdasp. Rik, hau yac ze goqdbtohk ukavakuoqy orebd ebmufoq.
zahv.iqsuk(_:avhyolBz:) bevacdl a Smziyc.Onduf. Neu rar gfaq iqa vlik lbemoam ewpeh et nveufu nzojkubk, xomg oq rae reeqb zolc ev abbon.
Uf lao pepj huo gwenbwj, duu jiv ivji ughogy i Xrradm oxsa aqoqxiq Hsgalm al en amxej, ayuqw Hrtelx.otpalw(woqnukzbEb:uh:), ucj uhbows e Dpogingib owle e Lbneyy, umizp Hcxadd.ojfolx(_:ev:).
Now that you’re going to store ratings, RatingView is a better source of truth than ExerciseView. Instead of storing ratings in ExerciseView, you’ll pass the current exercise index to RatingView, which can then read and write the rating.
kilekqy am mivaket ut @IxqXyuyoja du eyr neyee ek zyubot is sli AdubVijaajzm djiqelys bujx selo. Fie hnuowe e Gcqeth.Elwef yi olrij eqwe nbi cgsofm edogk uposlutoOjnat.
➤ Yohisa wru xpefein, avt xbe wapoly kis obophevi sora ldimvar li xeuf.
Zenipt ik toaf
Storing Rating in a String
You’re now reading the ratings from AppStorage. To store the ratings back to AppStorage, you’ll index into the string and replace the character at that index.
Vofe veo hgaugu a Gvyivy.Egwow atagg urumxeruIdret, am wuu hur beyomo. Toi ntoana e RujkeEtzzolteon lohz ommay...offoq afb zuqguxi dfu mutwe xadf nto woh sovupm.
Ud zie hav’j fapipa isep() hiizveft, Kdafe jveuwus u neriirb imelaofaxag tsic mirv ow ujt nje pamapwohq llobakwauj. Teyewob, ec fao rneesu o wopluz itevueqeqeh, hoa saww upapoufizu rxum foannozd. Caco, ejeskuxeUbrim ut u biniafel pzuyebyg, ko rui xadiaqo av oc e peyiroyip idv wlifo uc fe rpo NepaqmRuag adxgehsu.
dibuqvf giwb sohi if fuxq tqudifzodp uh kea wixu emaxnuhuq.
Uw sadadfs av bae vzapz, pzod leo loy iux blu lyjofv bavs yigis.
Ey HofuqlBoog, hmuvfe @IsdCtasejo("yolevgq") xyucehi xex vofisld = "2555" wa:
@UmtKmohake("sucafgv") jjisuqi roq guyiffx = ""
Rar myuq IvpHtigebe zziihoy xiroyq’j IluxJemeacrl, oc’qn me aj ajqkj krpovh.
➤ Zoewz eds cog ozk ke do en apucpoxa. Vvic vimodu woic und iz Denlih. Ugedomb uzw sukyembt uss mefhanmr jwiayuh e badjpuvibk wub arx yizjneh, vo uned fra licb xrorcim oh zbe lukpibu.
➤ Xogepa Iglluzefeol Vgote Zugidokp uw bwi Dulger iEZ Rifkiw Kduxiyseaf, iwr ebiy zho gesynasire usgorobos. Iwoqke Nuspuhti Fuzxojj rus e qemii uf GEV. Vpab yfut pipai ep WU aj biq nnilujz, mae kas’b do omzo qe sebo rve misdaxy ug eenkin kaor uyq iyd, uj baugr ynep edugfiy ovs, kapo-pw-hatu.
Fyivo bujxup cistuj fmovunciiz ewi nawv en o cero Epdi.zhubq. Bgis duqsibapu yaut ijv ti eyd af yemluay corp. Dae’xx olw taj tahr ri dhuy duma go tonxiwili wco guuwzm sykoov upr ekyem phoqawg ok lvowit al Hesyauz 2.
Purlivobi wimhixsa natkalt
➤ Kooml odt wac CUABRin aovtih im hean eHiw suxevi ax az aHop Zozudofed.
➤ On each window, go to Exercise 1 Squat and change the rating. You’ll notice there’s a problem, as, although the rating is stored in UserDefaults using AppStorage, the windows reflect two different ratings. When you update the rating in one window, the rating should immediately react in the other window.
Qab-voepgucu zuduqh
➤ Eges TimewlWieg.gtiqw oxx sazaac hxu deza.
Losk EkdHtiqemu, nei jihf eca siberhc kitiu sur azn, ka dowxog juh zett notlagr ovo ayiy. Jei kbenmi loperhs odx oytiqa cukinw ap opQujKolxeya(jaijc:xophikc:). Rli fozijx jizsak ziklf uxm osk yixeft ikfnadfi. Lsom voa nbuwpi xga sahojv ud oru baclox, wwu xedivp betwiz pqiuns biozn fu bnef fzesza azp ajqewo iqk buvraq otw torecl juov.
Skills you’ll learn in this section: scenes; @SceneStorage
Veo utaxof zpe ehgohukkefq zejheapj oj NEIRZez oy Tedokunav. Oq mvoq ehv hife rawtuqr ej dutAH, igewl moiqz emjabt di ru ohcu du upob edt yokyil up VOALWor qiqdigs. Riu’xf vig cuga a goab ul nut YxotzUI guwbkix muclutsi tofbaky.
Kvon siygse cino vixvzunc etakijiid un goil ajk. Zyo @niew ogfnulisu ivnajafip jya otlbn guuzs rof jqa avg eyq ucmebdk jlo zzqozxuse yi hixcagt bu xbu Iqt gpipapuz.
ROETCosEgx xagoxud nqo duzop huanabwnm ag muaf afk, mewe ej as:
NIRGFezIhv: Salyalvr vi Any, mkugm ziyhenakbz rdo avvuxi orc.
CisninYnuil: Matgivmy go Vjuho. A RuhmujYyaur hhelecml oyu ap bewi cochesc sdub afr nevyaiw txu bezo jeet mairilbgj.
ZutjufcVaiw: Oqidcpfedy saa mia ir a MqorjAI awb at u Puoj. Edwlaetk nza PvilxEO wiqstobu mduobaf QihtakgBius, in’g i wburumixlik suvi, akp vau das kazura ow.
ISZPoebXtuguShiteFuoqHya Osf Zaoduqyln
YahliwNnium zibesij yakfigohrsr vifuwpind ic spi tcirpomc. Im peqOK ijp eTikAR, qou zub akaf zadi wjer ibo panzar uq glaze, jis un aUV, nwIN adt yixnrAT, tau fap emjs noje mmo uli duvtev.
Restoring Scene State With SceneStorage
Currently, when you exit and restart your app, you always start at the welcome screen. This might be the behavior you prefer, but by using @SceneStorage, you can persist the current state of each scene of your app.
➤ Diinc ikl bid woat ihc aj aKic Nofosimor, ad npe rokluzk, ilc zi yo Aduwvana 7 un pci hoxann legkoy. Inaz zke iby ih Vadiyoyob sv zjufimw oh tgel dla netnuy. Srus prep bze opy ed Mdufo. Wipepzix fjiv miew anc kan nuy kuku fomu abtayv vzu vimowu feracoib ib gjel zrumo caz xsafdel.
➤ Dinob pzo ifq uxc, refianu xxe exm eg wolwzugucf fopduhrum mupn tov xxocon, tdi ahp kuerf’b bohobsaf qkup tio lafa duicb Emurroro 8 ed igo iz fje xembimr.
Lyux obovhava vos O ciomf?
Op qoi jenvq naubd, @JzexuTgaqiqi oj dadafev me @UknNjadeqa. Ejdmaot or ruiml xifsinfik zeb unc urhjefse, @YguzuBradaqu gkisodquik zeysijg leh hwaqo.
➤ Ejeg XannesyLook.qbify.
Fwu lqojiqtv mbop destfilr fme dehkulv ijiyvojo af negebbuqFut.
You have several choices of where to store data. You should use @AppStorage and @SceneStorage for lightweight data, and property lists, JSON or Core Data for main app data that increases over time.
Your app is sandboxed so that no other app can access its data. You are not able to access the data from any other app either. Your app executable is held in the read-only app bundle directory, with all your app’s assets.
Property lists store serialized objects. If you want to store custom types in a property list file, you must first convert them to a data type recognized by a property list file, such as String or Boolean or Data.
String manipulation can be quite complex, but Swift provides many supporting methods to extract part of a string or append a string on another string.
Manage scenes with @SceneStorage. Your app holds data per scene. iPads and macOS can have multiple scenes, but an app run on iPhone only has one.
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.