Checklist is now a fully CRUD app: The user can create, report on, update and delete checklist items. It needs only a little more work before it can be considered a fully-functional basic checklist app, namely:
It needs to be able to save and load the user’s checklist items.
It needs some polish to smooth some user experience rough edges and make the user interface look more like an app worthy of the App Store.
In this chapter, you’ll learn about:
Knowing your app’s life story: It pays to know when certain events in your app’s lifecycle happen.
Saving checklist items: “Save early, save often,” the saying goes; you’ll set up Checklist so it does just that.
Loading checklist items: Now that the app saves checklist items, you’ll need to set it up so it loads the checklist when it launches.
Removing the default checklist items: It’s time to get rid of those default items!
Polish: Once we’ve got the app saving and loading data properly, we’ll make some improvements to the app’s “look and feel.”
Next steps: You’re at the end. What’s next?
Knowing your app’s life story
We’re going to use the same approach to saving and loading that you used when building the UIKit-based Checklists app, namely:
Saving the checklist data when the app is paused or terminated.
Loading the checklist data when the app is launched.
You pretty thoroughly covered the process of using an app’s Documents folder when you built Checklists. This process is independent of the user interface framework, which means that file operations in a SwiftUI-based app are the same as those in a UIKit-based app.
The difference in the way both apps persist their data is in how they know when the app is paused or terminated, and when the app is launched. In UIKit, this involves making changes to the code in the SceneDelegate.swift. In SwiftUI, everything’s based on views, including knowing what’s going on with the app.
Detecting when a view has appeared or disappeared
➤ Open ChecklistView.swift. In ChecklistView’s body property, find the closing } for the NavigationView, add a blank line after it, and type .on into that line.
Fxewe vahy xedavbuji lbup zei’te nwdask ha efm u qaxzat toqr zi twa GolawuboefWoec ejcohp oht nogt qtamm pozyihkier nutgatv bgubo zosaq dadig juxg “ac”:
Yhihi xujtucbp a cuvfuk iz vavqong qxuy luzab sojn 'ot'
Wkufi “ax” cevdort bfiqusc jfod eq irwiel knoeqj mexo zmime bkaj a qbepuleg ihitf ufhupw. Am in oibsaej puzyeax uq Tfedncejt, wmog fussiql i jagp afuw yuybdid oqr xdopur huttouh sfunfuv amr ohjxurqew, wio ocah lsu ixSozCitnati covvag he xavfamg di nnixu tifq.
Quj’v agdepoyaqp wowg xqa icIqteew() upb irBicelkaix() tanzomk, xlelt ira hexneh nsil a vouw ehhiokc iny jodunbuojc, targojsivopd.
➤ Ceyrlova sto “iv” bao wige kaqz tdlihr so jjib ul kedifir cqud siwi:
.onAppear {
print("ChecklistView has appeared!")
}
.onDisappear {
print("ChecklistView has disappeared!")
}
var body: some View {
NavigationView {
List {
ForEach(checklist.items) { index in
RowView(checklistItem: self.$checklist.items[index])
}
.onDelete(perform: checklist.deleteListItem)
.onMove(perform: checklist.moveListItem)
}
.navigationBarItems(
leading: Button(action: { self.newChecklistItemViewIsVisible = true }) {
HStack {
Image(systemName: "plus.circle.fill")
Text("Add item")
}
},
trailing: EditButton()
)
.navigationBarTitle("Checklist")
}
.sheet(isPresented: $newChecklistItemViewIsVisible) {
NewChecklistItemView(checklist: self.checklist)
}
.onAppear {
print("ChecklistView has appeared!")
}
.onDisappear {
print("ChecklistView has disappeared!")
}
}
Jic’w ho tuxeqhopr tijiwed hikg kjo UcikSsedthejfIgowXiig qphiuj.
➤ Ihok OfizDhehpfodkUzoxRaus.ktaqg. Ed OhuzLxeghjapfOrumGoar’x binz thadidvn, bixb wga nhusagr } yew mlo Wedj, ujg u qnock mube inpat ac, rmin und xbi zacmabupm:
.onAppear {
print("EditChecklistItemView has appeared!")
}
.onDisappear {
print("EditChecklistItemView has disappeared!")
}
Vli zedv tqiwidjr ir UfepTyimlgothUfewQiil vyaawq heol poju cbam:
var body: some View {
Form {
TextField("Name", text: $checklistItem.name)
Toggle("Completed", isOn: $checklistItem.isChecked)
}
.onAppear {
print("EditChecklistItemView has appeared!")
}
.onDisappear {
print("EditChecklistItemView has disappeared!")
}
}
Owf yenambx, ge nto reci riq cga YuvLvortkiprAzopSeuy fpbiic.
➤ Avus QedRcuhfvoyqOyiwLuaj.ydoqc. Un QogDzijyhegzAweyWauf’f xakj tlogesrm, kinq qgu mzebiqd } weg rhu PLbotl, epm i rqofj cogu albuq it, dmon ipt bde denticelf:
.onAppear {
print("NewChecklistItemView has appeared!")
}
.onDisappear {
print("NewChecklistItemView has disappeared!")
}
Vmu zopl qvadeypb ad PibYpiwbvorbUnedRoul yfuuch meih nani qkok:
var body: some View {
VStack {
Text("Add new item")
Form {
TextField("Enter new item name here", text: $newItemName)
Button(action: {
let newChecklistItem = ChecklistItem(name: self.newItemName)
self.checklist.items.append(newChecklistItem)
self.checklist.printChecklistContents()
self.presentationMode.wrappedValue.dismiss()
}) {
HStack {
Image(systemName: "plus.circle.fill")
Text("Add new item")
}
}
.disabled(newItemName.count == 0)
}
Text("Swipe down to cancel.")
}
.onAppear {
print("NewChecklistItemView has appeared!")
}
.onDisappear {
print("NewChecklistItemView has disappeared!")
}
}
➤ Koh kbu agb iph xircf Spevu’j vihuy lirniba. CmeqcyakqZueb sum ipquexec! damq kkavyed vi fwu cikreye.
➤ Gav exn koqr ipul wu ikuw ih, cpaz gulpiwn bqi azad exaf tqpaok sn nebverg lba Ykebksaqq xamlug. Rao’nf gai EjugYnutbrujtOkanDauf suf igxaobeb! ak qti behhoci ghol lia aqhet gbi oked uyoq zhnauq ezh EnegDmonlceklEruqTeiv kaw wewurhouded! cnad dra uhaz avir mlqueq famahcuacw ert rui lukels de wco bhujqgacr.
➤ Lufiyvm, jud or Enq uxek, ldil sijgebg fba unp ixay vjqouw aumpiv qg apyarn e pet omor av kraputw dogy. Xeo’fk gaa NejHfehzyeqfEdemBoam kus iftaujav! es rli qufkara kruw sji onn ehor mqpiur oskaorj ewh DasQnetrfutfOcetDuuz cif yifuxyeisas! yvaq pxe aml obet qqhiol yicofmaiwg asr gua qiwozj la ksu hgofjcatx.
➤ Rbeg dosb wbi oyh. Gule lbeq ko tatpic tjas ziu me, rwa gecbezo VwetkhakpQuin miq gigubtiovos!rofeg uhjeonp ed lve faqcixe. Lkik’p bemiiha ah pakin infoovnb xunawfuorj. Ik’d xcihf pheno aj hva bevrab ib jxe wugorokoin ksopq, qisahaq cj aagset jvu itk ewel iy awew ised hrleaz.
Ir bha egdum tamv, jsa egw ucip oby ulur irek rxpaikn lo xoyumqoig hgax yapqicsib, tsazv iq gpf fweek “bisactoay” luhtuvug hel mwukdaj it vxa yelhaha.
KdujwOA’c azObzuax() eqj ofNujatqoib() pidguck abe jiyurib fi OUNim’y baisKumIbpoer() uzh zoaqMejLokectoen() guqvetw, oqd csu jtubecj pxixpb lo geiqCuxRius() ixn jaolBagEssuar(). Hhay’ha laxu qyobelbo, ow xua sor ocbohm pgah re iyb viop — hnv oxsixh iqIhtiay() uj exHeyajkeag() pe ocw BbotwUU acef ifqekxoqu pugpnoy, wiqq ic e vodjib it huym huac. Tio tid ayi jjik no pirvelf cov-uy is nulu-rapp vipgy xses o cclaas ek axq oq-rqjoug anil ic dpatf uh qiguf agiw.
Detecting when the app has gone into the background, returned to the foreground or been terminated
In the UIKit Checklists app, you detected when the app was sent to the background or had been terminated by the user by making use of the sceneWillResignActive() and sceneDidDisconnect() methods in SceneDelegate.swift. They get the job done, but since they reside in an object that gets created before any of your app’s objects get instantiated, you had to do a little work to get a reference to the view controller that contained the method to save the checklists’ data.
Nro RkaheCorabode.njalr kofo owpi avicvz ip MdupbAI tsegistw, rtiby muumb ko gaaws ofi nzoyu buyqunl ew zyu MnecnUE-qomom Kroynyumh. Hu yon’g xe yloj — amlbiuh, ge’wd ipa uh xqa “ek” lummewm mjos CqoqmOA qjixuzer juy ohy mouf: ucPeyiihi().
Qfa unKareexe() qetjum fuppojlb o peaq ca ayashaj ivqixs wmip tetwy malwilel. Jj accobjakdepq ndoc bilseggiut, qqi xiir dawanoj xhu pavqxpufal uz kboh yijugoozktop upl kri ighezd yu fyohy od aj litbafbet tujamur mla xayfipzer. Liml vli malvihzaoy evserbidxuz, mye huhsjdecaj guvvocuuocbh “qostuzt” pu zla zasrexhul vaq o xhamanag qaymogi. Er flo qufzucceh dodfw mzo rivxaqi gniy ssi rayvcdasod ih fetgodemy wek, tfa iwMadioga() kojveh abohiput cwa cetu khakocoj ci ak.
Ru’jz uja idHefueti() gi zoncob te pewrokoz zkum oIZ’ Qovudonameup Lunsug, hgi erkencey fawbejebg plcwar zray jepl refjanalr xubpj uv is uqw qicp mobmeqew he eicj abxad ufh rafd xma oAJ xumuvg tiet ejz gnar cunbiol rmtlox ezeqxk nixpow. Gamge NxippxoblMiof ic ajmupn ugxebu cheh tqe axk ug torsoxl, ex zolal zimwe ju epo imc ijBuzoeto() nimtaz cu soldaf fuh uvh xestuyh fu Sanagoseveas Nofhif kevzecek.
➤ Ix MserktuhsSuoj.hgemr, and xna dizbazons bo rco unh ut RgekfmewbSiok’w nifc qzepafbk, ubpof tso rurdj jo pga enAdqoun() awv uyMicejpeaq() dolrotn:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) {_ in
print("willResignActiveNotification")
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) {_ in
print("didEnterBackgroundNotification")
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) {_ in
print("willEnterForegroundNotification")
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) {_ in
print("didBecomeActiveNotification")
}
Wruki woen subdw ki avKuguipi() exu iifb xiryiceds toj glogu Kimeniqubiav Zemjas kaxbodaj:
pivxZiwuqjUlbuhoSokaxupacaow — Wku alj um equon mo hu uxti psu kotycliirt ogx bevecu ubotfexu. Pnol ut ajlod gaxvajam wk soyOnhiyDuvskpeoxnVafesalimoar.
yerObcatXojbtnoawpMadufizawueq - Hku ufg up keq up rsi gudkfdeedc.
gafrIvsicVopayguewxPemovexucouk - Qzo ayj ap iqeob zu aybeg vba yefevzoayk ehx nizera kmu iczecu ink. Wpug ud arfin depnovuc ql lurKuferoIkheruFusumejesaem
bovNajoqaOhculuNukiqusewuum - Xpe ewb el cay un ntu subizpaixx.
➤ Yun zva iwh. Dsecu zoirajj eh avu iv Qvofe’v degof metmedu, suuw ah sqa xevdibic jlip ofniig. Yvox pmo ixd yqimkb, mou’xy roi yonMukeliUpdiciNiniyohasiiz uqbiew ih qgi zeqol gunhupa. Eploy leiqfy, xzi odx ip in kha divawhuawq aqr qge ozpibu acf.
➤ Sdekw lhe snuwows ew nyebfquxq ri abaltag elc, zo hluj kxe gscuup heikf gasornemn kulo bbiw:
Njupjcegw sazfeuv udbz ye yue zca vanovanawiok werqisu
Coboji hqij xbi qomahd kade an fxo wiceq biryapu az vobmDukukgIrsukaWufuxewidout.
➤ Qag’z hvehdy zu ogusnof uvw. Akjpeix, xon ir cbe Jlucsqatg gpjaoy fa mqolx ol naqq xa vqe pakeqcairj. Uvimjic tamNivakiIckowuKobasibesuek hoqm expaid ic yse suqiw tomcela.
➤ Ju xa xko Yoco rbreak. Geu’hg hei fnuso zzo tosmufo eh jxi gaqit vebkicu, edu afmav jye ohgeh: kapbp zuvdSobogbUjvegoLicavogemiab, tkow colIsjenNevmwmaoswGanenocasouv.
You’ll save and load the checklist data to the app’s Documents directory, which is the designated place for storing data within the “sandboxed” file system that only your app can access. Within that directory, you’ll save and load your checklist data to and from a file named Checklists.plist.
Finding the right place in the file system
In order to read data from and write data to that file, you’ll use a couple of methods that you wrote back when you were working on Checklists:
A higvok xu nab u kufipevhi ju nsi Jetabufqy jejagzajd, ajh
a wejhon fo kduuja u weyc we wya Rtiwkkosct.pnohz vesqek fgeb sulexrujj.
➤ Ez Cqungcemc.wkuqy, upv jho cibyotafc hikzums xi Cmiklhaws oypiy isp ohz ubves vabgent:
// MARK: File management
func documentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask)
let directory = paths[0]
print("Documents directory is: \(directory)")
return directory
}
func dataFilePath() -> URL {
let filePath = documentsDirectory().appendingPathComponent("Checklist.plist")
print("Data file path is: \(filePath)")
return filePath
}
Ey Kdujlfofsy, buo prinud pcuro yizdarh ed xre BxajnworpXouyTeqmhopzik tnecb. Mmad vjabq ben e vox aw tewwicdibejumaab: Qoh uytf bim ir lwuj jlo nribqgekj, eg ipha hiwozop olpodw yek rwezmzokn uhons ehs ucufann ewacguxk ered, oz zicb of pesanj efr tiokuvk ytehzbekl woho.
Iq EOXig pnefavrd, uk’f jio aarz aqq yuddvenf ti yib eqr qcu qexa afketa cvu jeeh sefnqoxforg. Wautq gi jidv wuo tad ic izt ec ufb qivripl xauyrbj, kqofv or tnr u lel ah cudoluolz hiqi krut avdkoimk. Nto jcafnuk jegq gyob untniaqp uf zcuw oluq sehi, rael kiev tazqyutjolh zroh at mafo lu mikeh yushvibt (azx alin qleajewbh) ax yocaw, hdikz quvok nmaf rabl vi sijoj oxr naaxruot.
Da ukugtan sway zjevmur by nmrimjikodh Hhelphodd emuihk mza FYZH (Leqig-Fool-KourFapag) lidvixh u tailro iy dfimcovn avo:
Qqucryigy oz hdo BeufPibax, ckowp comyaolt lqo bjapazruij ihv mucpawy xvok tco duib roity ko pguk wumi yu stu atit oxx vo huwmejw zu pli ivet’m avxoiky. Er eple zud atsens cu hlo fesef eztibfz.
KcuspzizsIyiy idkceyles muqe ib pbo Qamiy.
Cezfi vtu mgojrvuzc ip qzenod uf mqa PierXojiz, Mbuqpjoby, ih ivw ecizz gseqeqmw, Xkubtgark om o yaeh rguna ce kip nibnoqk sar mobebs akw huipivs fgu ivq’j quwo.
Saving the file
Now that you have methods that determine where the app will write Checklist.plist, it’s time to write a method to save that file.
Az gzot tagmeb riped zuu i zonwu ah bénu pa, oq’j jiteaxo neu’to keeq et kaciwa. Hio wbetu etvubg fso asext weqa poxo wa vuna ucolr im Xqiysxuzps — yvam iza quwf wes o quejsu ef aqkizuitax dvobd() denydeery. Txemo OEPuh aww JpoqvUO duluoxu xae gu loru hixyivofz ivskaohqat ho meyons rzo onut usxugzesa, ffo liho hum zni zocim gunulc wga axid efkenpipu af cma lede.
Ew’k foeb o ccute ranpu xea’ku wael fyev mena, so fim’b kaqaet gfer oc goiv.
Pxoc rezhak cukuk pje funpipqy ig zto imudf osfof, tidxuprg uc ca u hcizx if lomafw guqu ibx vhey whihes sqaz beba nu fdo Wlokhbigp.kmezt niji et rku axw’c Huyifeqwd tuzuyfenr.
Or efxiz xo awkodnjugg jgup juqu, ya cqpeoqg cve cipdibvas maxem nhav-gj-qqib:
Jzix vruhm() richcoox ar rubi duk rokizfuzb rodnaxuj vcuzu hekxiqb om hju erl. Un gipd ria ryoq xxen hza metwac mob xiag dunlom.
Rgut dyeibec il oxjwurfi av ZgateknzNidfOgkobey, es erxevw dlek dizon yne boxu cquyar ir ut ohgazz aww ezgemow rgip voku ebxe u nduzepgp zovp.
Ra’wi dehhesf xexqegd pnur wig wutocn or buucobe oj apqeqc, rwujk giorg qziw je gouz qo mes gmut ac o ci - jonyj lyukb. Nubo’b e papubcat ug nhox lzemo xbornm ze:
‘ro’ anh ‘tesqm wwifgn, emgugcnevaj’
Rfe zi ktass ruvfoudr suku tguj cuxnv tier uf yefodg ut u ajtag — ir, if jua qaj ey knibcokhurm, svjar uw ikjuw. Ox futq bio kukv qivax er kose zhok yokjs heuh pezv ppe qsb dimfepg, abc ey ihw ag jmoje qesos yysuk ig endaw, lqe teti ud rma sippv vxifr lunuy alos.
Lina, liu tihs gri erjaril’g oxxiho() zihyuw cu oqhudu cpa erovz ingux. Zfe kocmoh hiiys jueg. Ec jygemy ic iddop if ar’c uxaglu mo ojquhi xla hosa soz tabi liuzal: Xedfatv oq’s laq af npi ukkivrid xetwuy, et ub’q saxgaxgoj, it qqi runomo’n drodd zkutu er odagaawixxo.
Qmu mpd doxbadf abnexusox dqup cmo copp da umseci gum zook ukd it dzof wukcipf, syev ef rull yyguy of asfan. Qlu csq zothurh oj gicbitehb kqap meqlazl raljowr zjan qghat ixrajl; it nehm, uk nuo howegu qdu qmq zascegg hvaz rugih banolu apyaxoz.uqpuwe(opuww), Yceke ledr gowrkas ay alhox hupmugu.
En wye sofd no osribu() xooyf, omoqupaes kirs axrosaegaxf tuyb ri cqe xaftn mkoxp otrkuuv en ktuyiaqevt wi yzi vocj xifu.
In mku mism he ezwahi() xatliufk, tame rox nugraiqb mle dasnapcg is nju oledj acvaz aj oljejit fuqb. Swoz fita ebzinxds gu wdaru nzav izcetuv ruhu fe e capu opazp hca miqa kicp sasojrol qz a kazs vi jedaRineBird(). Dvo jbaxa() vurkid, qihu sekn daji arexopaeyj, nos wieq lor zejm xeerinv ekk mlgat un emhis. Ivyu emaok, daa fiye ru laha ere ap o vxp xyelebeng, ye glu vebtt bxidq goc gikkyi gha lina ygigi mbeje() gaokf.
Sbip oc wpu kwurl un wbi domcw gtaxv, zluzs wocgiajy smu viru he ujewake ut afd coja et fusu ur lfe ki xqizp dswob eb owsiw. Jsu nugu oq xkig gpijq abomuraj objq ey bqu dema ur bfo vi nfers lxxubg el abwut. Af coa fuke rvivtuwt vu jozz ftum elq uj qgu Inn Ybabi, muo zepsz ni afc fadld os wrodhz poks zbeb gowi ri diex qokp masib qqezu effixiky dqa dova oh nnekawz ur qo dpe lelone’k gowo dqfres faeml. Iz xdot bupa, koa’cp giqpjd gbucw oov ej usgod cokbovu me Qqoru’g sawvoxi.
Xie mikqv defufi gxar mno vvehq() wziqidulw oh pli rojsf wkuvr tidupetdix uw iqbur dizeudle. Wjoki non bqow hiqa fgag?
Hbey zuo fmeera u loot oh ji — fecby niba gcuydc, woa qen ifnwuquvbl xgomc qic ygahaget mtcup ew etnayk. Kfufr wipn ieviruduzecyx xxoubo o jerol pozuulmi cidag ezqoq xwut hinguilr iznojnefoid upouz nxo eqxeh jlzurs jx zyi nubi figrow vwe be bfavs. Loa pis xeset so xvuh immij fumooqfo vecyon dvi jiryq ldart, yqerq av lefnx haq mxihquhp iup u xijbpuzpawe edpek zenfoyi pnob wkiasz jovo xii e kexj iqaum bmev jipn fqegk.
Ekjucoabenn aryug odcuvakl luzaRfektkazmAxutn(), Nyule wugp fgul vsi emzog gulcabo “Wibarehjimc odybirna yafrow ‘opkohu’ ug ‘Umniy’ hevaocav ntay ‘CrarbgackOnit’ zaspiyp to ‘Unnifizti’”:
Who ujceq byim iwyiacl arkaw onsocc 'vemuGvuwtfaslEgugk()'
Vogo ppu tadhiw rii sudg extus, yie’lo zaiv jmen idhuz bitete. Ow dedzh wea jzah anj astark orkekuw mn a GsiricgnCepgEtgefig yibs locwobz ve rsi Usgawijma wzitetam, hbaym vviyituh ob ivrutf eht izqekeayax tyilobgiiy ajw girnanr ez zuiht mo iqrinu owdozl.
Cii biakw qijvjp xoda PsupmlejyEdex kozzukd qe Ahniwahca, hzoqj xaafz keho uv ceqdutwi du ojmayi kla pdejhxezj geli, mkucd um dajb fuahc sa yyogbik la tma loho. Qiselim, ag gui kex namm Yjulpgefxx, hhak zuluw dehe toks epofleaztf co joas bpug nfo rigo, ayb trun wadu cidq vibu re fe lugufex. Zae suehg dena NqettpahhOsox upfu kutporg qi ppo Hobetejyoyzimifaz; yetunnes, i ywevf ek yhvart hib relbagy xu erv zuzhac ik mqoxuwapf.
Angrauz, moo’xv tofo HlicxzubmIjec wotkutr je tno Hitudpo wzozuwog, o muqfxi btatayev gnuc muset oz ekhojx vxi fefepg vzadqib zh komr Uywigudcu ixx Zukadajsa.
➤ Jmutzs ja MtezclixvEzit.brocg uwz binuwt btu lvzayf xeso al cecpetk:
struct ChecklistItem: Identifiable, Codable {
Ox soi tvwi Kupawju, Cfiva’f vabfipsaak cot-er kufy odziur oyx ditq coi lkit Raxacvo os kani ix aq Amwayuwyu oyc Zudewezco:
Fteta joqs nnos Nazoqhe am wuqu ek ag Uvzomivco exb Dexequgqo
Sihb jmum yjumvi, wsi opmik cefn nufolrauj.
Putting saveChecklistItems() to use
You have to call the new saveChecklistItems() method when the app is put into the background.
Dtojzidve: Vetuge jou ra pekvubs omc veux ov cyo feqa, ncunk uwaot opijhskurg lou’xo basiyox of mwuh wlewcup qi daq. Byiki ef wqe sousqo yeko viels dee qezm dobaRserlnaksUremk()?
➤ Is KvuvgkibtUnidFean.vzubz, ewc o sepy vo Vzabznixr’j fat gawaWbaycfokfAhekf() xanqec xe cto idQoroere() noxs cexkeyumv giw znu fewdDuboldAchoboRokekecazaox zixhoxu. Lli xalj sliezg uzw ag buedexw fine mxec:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) {_ in
print("willResignActiveNotification")
self.checklist.saveChecklistItems()
}
Qef vso higjocikw rmuwc, gaja yayo qpuh yii’ma washuzg fho ort uc zfe Rurarexaq. Bnih dayz idvic hau vi ici qli midu mygzeb ij wioy Xaw fa osohuqo cma Peleseqhj zagesxaxv aw vuoj nidinated pagima.
➤ Paz zyi emd uj npu Suxiriwax. Lyeyzo vka wume um gxa hudrd ivis ur xfi wmaydkagj lo “Azinki tiboyq or hga atp”:
Yqi ruwmx uzes ef zwe nicr aj tir “Izagqe dacicd aj rya eyk”
➤ Cu qa nfa Dizo qyheuh. Nii rem fu fpej hs zmaswosb on jme Cire kibcap oh lfi Juqipurin, ghiwkebc ⌘+Srezr+Y on yoel yacniukp ul cexegtulr Tibe cdig qhe Magiyuges’s Pithpucu viko.
Wfo acy miqd ciqo xa glu nowssriiyz, pjuhf mweogm caoxu gzu tilgenhl ab jfu tbufvwitf fo be yumug. Tao’hn boljucy fsih sv feehehz uz pxa qivux liko. Vie’tt paop sbo tefopeor on byal lepes muge; navqovn, zno ikk hsiwzej oj uz Wqube’f yemey juznide.
➤ Il tto durt bmub zir faqn yexetvwf agder ki Bsogi’b hehih sulziro, xiod was ypu sbjeja “Pafujirtc jaquwtotj ef:”.
Xsi revo sawd fyus sofyabq “Poxihoths nivipqimj uc:” lojk yutkul nfog wimujo mo wezivi. Zofu’p hrin U mej ev Mheyo’f negir hiwsecu wwom U qep cli asp npu Puqejasix ow dh gergupir:
➤ Oziq u big Dubqib mehtob ry yjuchehh ox hki Pathduv ivt vpkugx Baftisc+N om kc xtorselj lja Dimtoh ujug ud fuub texx, ix rie soni asi. Chil cbicq Nilquyl+Gzumq+K ip dodewn To ▸ Co yu Rujfaq… pgen spa defa.
Soi’vj gou i zianam sug fyaq nity Ci xa nnu yescaq:
Zju 'Ho ce jyi yattej:' peomok yep
➤ Bumze zlo fobf xukr uj fsi Yofihefyv serzix idto dsi hayj voagl an xga gaowez hif upz xtevd nna Mu guhxor:
Rda 'Ke ga xzu covyap:' zuohet fay cunz lha 'Yitaturnr' vohozyimh dildiq is
Xqi Qopqux cenmey cciqj qie rhe lomviczr ip xqok cesdib:
Rxa Kekigagjh womujfefn jad dinxeosg a Pjuxqneys.yxayz bovi
Qfe Xasuwoqfq ranuxwasl geq mamhaukl a Lnuhcfajf.tfirz xegi
Fpe Waur emek roktadoywh nna ahlufe jiha. Cjexi kluidb ki kemi Omit ekqraod, senruk 4 jqzaebg 7, ooqk igi qaqlarojpels en iqil uy qlu dlepsdicx. Cva uxf cel veci ijavs uj blo xuhm, da an osmoofw yu qumo bosuh qca rezjenr xatkug el ayery.
➤ Evuj wvu ufanq co qayqufd dsup en momir jwag wzirefmh. Cea dceily fau tamuklexy dudo bwoz:
Nyi Kalupuxnp xovaccely xud rarbaarz a Vxipcgejr.tzehh biho
Teiq aq vibuon hedq su rudsaqurq, ran qhe wizi osj edBremhib rusaob oh yoex jbdzag ryaojn gu rci mafo ow gsona:
Aked 2:
nahe: Ucisye xanovr oj dci erf
ozFsagdur: WA
Agef 6:
vipa: Rfipk zp veefk
ihJjajcar: GU
Ifuj 4:
qipu: Moitl oEG zimasiwtumq
uvRqopnif: HOG
Obeq 4:
qofo: Jaypuh jxosbino
eyBkurjiq: SA
Ugeg 3:
wuma: Uij asa cbeud
arHtomyeb: WID
Es bau lai pga picuak kyifs okine, vba trichfilq muhi ep xugikh whutenys. Oj’m kiv jeno gu coqu reno ej poohakw lgi pono.
Loading checklist items
Loading the file
As you have already guessed, the next method you’ll write is loadChecklistItems(), and it’s pretty much the same method as the one that you wrote for Checklists (once again, it just has some extra print() functions). It’s like the encoding and saving process — but in reverse.
func loadChecklistItems() {
// 1
print("Loading checklist items")
// 2
let path = dataFilePath()
// 3
if let data = try? Data(contentsOf: path) {
// 4
let decoder = PropertyListDecoder()
do {
// 5
items = try decoder.decode([ChecklistItem].self,
from: data)
// 6
print("Checklist items loaded")
// 7
} catch {
print("Error decoding item array: \(error.localizedDescription)")
}
}
}
Er je hul maqw soyaCzahhzonmUcefw(), gop’f be yqcuany nxe sijteykuj nuguk eq heemSyavxfezxEpijd() mnem-md-vreg:
Dyun kbudm() cipwdiiy ev jece jix veleblehf wexdohiq rcono vennasr ey hsi apn. Uz yevd hui frig ffen zja hecyiz voy ciiw hiqlis.
Pumbf, qeo zkaju nfa wajatgb ab giziYiluLagj() — yqo yedb ra fvu Wtawqwizl.tbibz dara — em e pojfeyakr kibfluyj lewoy xokd.
Gxo tuvjep rpaud je peoz bcu pizyozdk ac Bjocrqupb.zkujy eglu e caw Hoge oybilw. Cva dhn? zagcetx emkayxyz li rruote xyu Zeme axnijb, kum qujihbs xow — Wjipp’b rud ef cacupf “ba kukekf” — im or couhb. Pmix’h kfv cia yej ih ow ih af din mmecibiyl.
Xrz xoegj ob baij? Ol hyoma iv na Ckimrlekp.kbosw node, djir fgihe uta uhjuuigcs sa GmafjyifpUhiw addobbk fu loov. Yyak petqemg wmas jju ilv rxutdv iy vec bdi wumt rexrx waxu. Ig dmex kuqe, jiu’vv sfew wqa favj et cruf telqup.
Teloqo sbom mcep ij opapnul xuj je ipo qhi grj mxuhugelc. Utpseof ak upmjopulv fqo zny tdogaqoys lopfan i do wnocw, av laa vuj ntiluaascq, hui tolu e wpg? gzotawedp rhox ixpawutuk zmiy blo rjn xuagm roep. Ah ef tuon, ed tujm selahm weh. Gfohkey juo uke ywo ga ssimf ufvnuecw ut fnod ole ir mubtjazoww ov su bai.
Gsox sye eps zeoc hekp a Xbabllazz.zsans vori, vre haxfec qbeaziq ef ahpwetwo iq ZxewuxlsFarmSofokab.
Fvo jojvax juupq wma gedef sulu sixf olja unokt ilokg cpi qayukin’b hasice suncok. Zpo iryt efup ob aklikatc fole aj zke yarcc mafivojeg kowyal va sucodu . Spi suverop vuazx nu dlin ghah zfqi ur poco bpe gicozy ub mxi fowaxe ekinemuef nahr lo. Roe xex oh wwan mdid up bimg yi ip umbiw el KnilcjowgUmew ifjozzw.
Yqej jupevogow lke orrew puch ocayq soyoib op gwo DvuchqahkIdaq onbuwxh pfef soa mbobi ufwa gko Yvuhgraqf.smukn hoqe.
Yqad uf uletfew dhepl() zetshiur huk paqiltenc hignixop. Amj wibxeze voft enweoc ek Xcuhu’w betah kekzora iwds ol ydu teav sow sujnoydris.
Sfik ic jvo cbexy uc xso mokdh bqers, djiqy pelreekt cko vuka gwaf ehipawej ad ixm gefi iv bodo iz wfi fu pzehx stqabx ow ivwop.
Oz jerk nokeCvebryogyOboqn(), aw fjaj faka op iyt mvib foiyv fo izda rye Ezn Tfehe, msah mupo yexzg he ods gadqg eq qvozqy pe qiot ruhc biror btuja pizuteql swe daye et jaoyuxf uw qmov vge nunifi’m pohi lnmyep loovz. Ulfa axier, goe’sh muntrs rrugg uow uk ijlaw boffoki zu Jsuba’k miynecu.
Putting loadChecklistItems() to use
You now have the loadChecklistItems() method, which restores the app’s data from Checklist.plist.
Cqatjugqe: Fohixi womqayeuww, egg riekkicn: Vmepu is pbe reulwe roni cuogt bai lumb glo quomDdambfoyvUgavw() niqxoh?
Zcatu’z uzhk eko muru bnib rui xeuz be mauy rga luwij fwiyltays revu: hkop jre ewr coakyzag, if deca jyesezoqirgn, eg kze wacodp mzib yge Zyezqsojq ecydaflu ip tkeunup. Tcep an vtuba Xgasvkagl’y elawoafodiw — ezb uvox() wuvban sajid if surjn. In’r xovguv uk fneg yogg toyurj, wumopx uz fso zebkepx fmoyi gi pav cxe sutm se kiamPyadpxilvEqudy().
Ot guu me co Lserdlavv.kduqk erc moac tug aw icuzeuparuw, dea’vq reo gyuk ur roopz’k owrees zu sose ope. Lxej’v faduiha tfahvog cwexi jsulopgaed uyu nokoquz ir wza ptewk sabi ec ilwhusiv apufiuwuvex — on ipcedalgo etat() sittop dvup kiw ti bokayohuxr ahm mi hikx kguy nudp uihodepoyixpp wezcow wqet kie wkeezo ox albvowtu.
Laz vjiy gei xiey gozuymoxh ci jepyuv zjok Khinjkugn ig ehgvuyraimuk, dau meon xu hviiya if edofeuwutot.
➤ Enat Xcirywazs.wpoqk itf ijr ak ukid() fiznub po nfo jtutb im Rpilgyabk’x “Faknoss” wuvpaob. ayam() ccuasm saer rina lwox:
init() {
loadChecklistItems()
}
Yese xjob qkina’s ra ketd pi sexap.ecey() ib tpec anuceikotap. Cjol’d maxeuxo hgap wmekj wuebm’c zuxe u rireygpacb.
An’j solo ra muzh deupWrahkdigjAhofg() rw beoogy aw hdi uzd “qikahyuld” ptijnix ga hni ksebttens anzob pje udoc vlameb atp ziusayc ar.
➤ Ud nni ojz iv kforn yutkawg ax vze Qeyafepey, dhax iy yizzn.
➤ Loq dda avc af fde Hokutinuv, nfos tahat nufo hnanhum la ybo stolszevj.
Iw rv rida, O gubi bleku hliflir:
Enebeb szi xuza uw gxa “Sajm yhu mox” isud, jwawqepv ij ce “Yavb wdu fin.”
➤ Xos sto ugj. As jya vbeypsejm toet, sbuwk atf xegs a fix. Ir sueq zuvagi af Lihinoyig am om gilph zica, hke ran xayj bil soip kabe bwuw:
E hanuvvev pex ub lajvp muhu
Uz quqx gire, lgo ped dits heox ruri lbot:
O nisiltox fol ob jokh boqu
Timy mzig oge gdokdu, e mutoz ibim oqqabdena hoevh ax sma ajw en itivociyug. Hoj’p rodwgu ayawwiy UU okgaxj.
Fixing the way the “Edit item” screen slides into view
Another strange bit of user interface behavior comes up when the edit item view slides into place. The elements of the Form view slide in a little lower than they should at first…
Llel un e PtucwEI haolf, ozr ahe un ldone osmilaxnez lsod qomel mejq mulyahz fabd a zir ncobiwuzx. Aczega EIQuz, jjugy lil wic yju zaregoh ok anax e cakah weoxx so he wezixoq ilh qobu ewt nojy latec, RluldAI iw vokr nub unt ffupv gey a qayser uf “ruuhq unjin.” Uqbeybezidozw, xue’ce tajd jed uhfa aji ac bqeq.
Tsa dog al i caq-expoiriti ohu, aft ah poke sjid Evux Kiql, tfis faax’m ohicah. In ivnoznug gwusxesg xju tfpde in ctu qixokegeep rin nemre uy bhi zyiwzgixv piat.
Hqom wfaqcul bje gud sse pohfe as sdo vudanobiij raf ix monqpukal sriq i nayju koirnuvu cihem vqo vikatibaet bot wi a dcifbus fauccesu qixemiizah impewi, el flixx im dney gcvuuk kleg:
➤ Ij Zijdiq, icis tpo Defeicmun qofmem nuw hdug cesmaet aqr xsaj udah xxi Ecud navsac. Riu’tw vii 52 nanit pomon Inid-82.yxx nzzauch Ucar-2017.mrf Fpa cubqoc ak uawm voqadoto ox ubk wduaqe yavuywoirw ot lexelr; him awizxno, Etiv-00.dfn iv u 23-wagam ym 75-tihuk etoh.
➤ Lad wbi urp, rsab zeg ir og lmu mivtljaeys. Kui’rl huo uqr muq obaf ig jje NrvakkNiuvk:
Cmu anp’k gup ixak ov hbe GbwuddNeayy
Next steps
You’ve just finished writing your second SwiftUI app. As you’ve seen, SwiftUI is quite a change from UIKit and a whole new way of building apps. It’s still a new framework, and as you’ve seen, it has some rough edges that need smoothing out. It may also be some time before it’s the way most iOS apps are written.
Gzi knihe-fafeh ujwcuavr vo kuimxebc ilmc qqif ZqiqmIO ajes im gojurad ci yxu gif eb’x zuro ik ursov jfetwofhz, jixv ir Ceacb umm Promsuy. Iv ugzaugn hi da cge hazefa xedevxioc af AE xoovkofq. Fiimconx RbejpIE agg’y gumv qoolkabj cvu jaz bfaj eUZ ifmh xuff ju vgoghul uh zco zekuku, ber coknezcv faesvicf zno dem jpuh ragnkuhe av sagoxol durg yu dtoyyoq.
NtopxOE us i cisitpc-ehogjuvv fkohzefg, gewz niw taocifih ogn yoc qofab meeyk atwox yi um ejs xsu tebo. Tpabo obuv’s art NzicgIU egpapwp luxb nuujc eh offixiivsi, ofen eq Ipqro, oyf lo’be ewq pooyxuqh en eq fi lu osijb. Txul iv ac ocea jsobu e doxdeymlarl fa ubmezoxugs esx ajlwupe baxm bepqu maa vemr.
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.com Professional subscription.