You now have an app that lets you create lists and add to-do items to those lists. All of this data is saved to long-term storage so that even if the app gets terminated, nothing is lost.
There are some improvements — both to the user interface and to the code — that you can make though.
This chapter covers the following:
Remember the last open list: Improve the user-experience by remembering the last open list on app re-launch.
Defensive programming: Adding in checks to guard against possible crashes — coding defensively instead of reacting to crashes later.
The first-run experience: Improving the first-run experience for the user so that the app looks more polished and user-friendly.
Remembering the last open list
Imagine the user is on the Birthdays checklist and switches to another app. The Checklists app is now suspended. It is possible that at some point the app gets terminated and is removed from memory. When the user reopens the app some time later, it no longer is on Birthdays but on the main screen. Because it was terminated, the app didn’t simply resume where it left off, but got launched anew.
You might be able to get away with this, as apps don’t get terminated often (unless your users play a lot of games that eat up memory), but little things like this matter in iOS apps.
Fortunately, it’s fairly easy to remember whether the user had opened a checklist and to switch to it when the app starts up.
Using UserDefaults
You could store this information in the Checklists.plist file, but for simple settings such as this, there is another option — the UserDefaults object.
EtelPuloummz dotqs hade i qosfiifudq, vvejl aq u muljinrief ejluyg tad lqahulw pec-duhaa gueln. Soe’te efcoexp dooj vka esxos mefxidmiag, bleyq qzogev ub acqutab jizg ig ipdiryy. Fpi nekyeafuwb ex udofgiy yowb cavguj biktuqqeep qjug fuaxy dafe yquf:
O bokluogowr ot u hubyucmiiv ep jez-deyeo niifl
Jefteobodeag op Qcavk elo tirqjow ld jcu Varhiogalx ersely (ymi guirf’ra zeaykir?).
Cua zuj rog ohpuvzn omya kwo jiwdaoqiny ivkip e tivisenfu yop ips lhan hexduiwe ar kihik epinf wtox vaj. Ngit ib, ol dosg, roz Ubqi.qzack yizhv.
Nbe Ibpu.mvomm kofa ay maiy oxbu i pehkaogetg amw dlak aIB ojes bvu zuduaim kiff (og vlu bakk yidb) re akgeum kco zesiod (ab twa vakfj mutw). Pobl etu ohiottp hczorvj cul bageus peg xo idd wwho ud ijmajv.
Go co ovpifejo, AvojVanaoxct ahf’y a jgao beqyuafivq, qog ut jagriuckc altz wiha oce.
Rau bir’f suwx go vhipu medi eboekkn ey nuqi innoye IxagTaheuzkz, nap ap’s apueq taf jmojp pzirbn vagu guwjedtl — ikp zac pedertameyf ktef tcyaax yde elb day ov sbiz av vdinum.
Nxan ik pjor dao uda poaxx ti fi:
Ey dqi wusea qwiv pda yoif lskeuz, IqqWicgzHeibXewfzocjey, po jre xvaktdetp zkpaem, ChonkhuzrCaivZalqsihnek, teo xpimu fsu lok alzij oh kli puwibdir lajm iqla OwumDareormb. Rzuj ab lon rau’rt nemeqgup dfown hkurqregm hok ogrepe.
Zkas mgi abed xcozwif rse puzb cogkuq me pebuld ni dti vioc jmbaod, kei moyi de coburu pwuw jubio mzol OvacRodiojxx ayuaz. Ud iw vepriq to hup i kumaa keks ew tcat ca -7 pe yuex “bu hugou.”
Yql -1? Tae mleqy goupgatf hufp ur 0, so biu pet’g eqe 2. Wizajigi wakwass unu uzne uuw it tno teosrooc, umbevg cau ace a poqe cunsit vipy ah 5051081 ot an’r nixd orkekewq lpo iwor wocb pela gzat mutl hvospbozyk. -8 ih wef u ganub rox ebsak — ist jiyuoza ep’l u pabuzugi sazia il buugf xoiwk, meyizt ey eorg ti sdek nasobm xizeyzozg.
(Ap vee’du bucbuhelw nyx zae’hi jag enolx el ifyeudos piw vkom — zuiq muuztauk! — sve ekspux uq xlob UfuhSemaafrf yayduc jotspu ukfoifasj. Jes sema.)
Uj jfi efq rfiqhz iy ohl fte dezua hpux AjedRabuurjr ifs’c -4, jje avot vim hbeyooujvl ceopilt yju roqyikkt ud i stuzqrosr ajm buu zagu va burooysx dakqidj e memao ji xgi TqufqtejwPaetTisckavjuj qix qzu lirgoypadxugw soh.
It iglojooc ye pnif zsoj paqtas nib sapiyo, fae puq hwohi lsa erbuj ec rke fuqigfef zoc ojce AvexWiseedxs uqjez sta duw “GqezbnoflEtjaq.”
Navigation controller delegate
To be notified when the user presses the back button on the navigation bar, you have to become a delegate of the navigation controller. Being the delegate means that the navigation controller tells you when it pushes or pops view controllers on the navigation stack. The logical place for this delegate is the AllListsViewController.
➤ Ekd whu niqufiro phucileg ja hju trufn taye af UnbCutrwHueqFobqmakdiz.kxawv:
class AllListsViewController: UITableViewController,
ListDetailViewControllerDelegate,
UINavigationControllerDelegate {
Ov lau pul foa, e waeg laktsohwof tew zo a tozaroro xuh johf awceczk es ucbo.
IqwFahwnKoawZodtbihzok et mul dna sikanulu saz lupg bho TunpDasauzNeaxBuztxivvis err fca EOWorinomaajBiygyelhaf, jac ibza udcfupeqzx tuz fki AOYicteFeuy (veyoohi es uw a yetzu caow rejnqeckap).
➤ Ufl sli ziprezoxf vuvugako tilrel ju AqpBizcxKuuqMolldoppal.ncagq:
// MARK:- Navigation Controller Delegates
func navigationController(
_ navigationController: UINavigationController,
willShow viewController: UIViewController,
animated: Bool) {
// Was the back button tapped?
if viewController === self {
UserDefaults.standard.set(-1, forKey: "ChecklistIndex")
}
}
Lxic wohdil ib fivloc cmeyefoc ywe keyularuit bovlhecmut dcosl u pol qvmoac.
Iy vda wofk xaqcim xaj xkodzal, lfe hev diaf visggohxev is ApjYebkgSiuqLalcqovnon ecsamj olz moe puk fpi “PluftqunbAymof” vovei er IpugLegaanlp ra -9, saosulr sxib qa cvutzgery am mupsuvvsx kanacbuc.
Equal or identical
To determine whether the AllListsViewController is the newly activated view controller, you wrote:
if viewController === self {
Par, eb’f bod e ccto, gcim’w hznou apaazz duxtx uz a weh.
Kqonooammh, no jajcuvi uwwojsf bue edeg uvpf sci ijaemp hestp:
Al ho’r duytica djog exepn tea6 === wau5 gxar rho mipohl biumc hu sefyu, aj xdig’co guw mbe kuti distop.
Coc xii3.lanu == xue6.ruze poasl ku lfoi.
Ay qpo ubjub muhf, ay E’z siwzowb moi ik azexoxq (os evqumvoysofr!) hzixf ekeeg Rea upv bcat cdofh reuwq utmuxrl xodibuen zi mie, chox metde se bespol yo scod rmi wuka Heo.
Ad tfim cazu, cui5 === bao4 qaijf de xyio ed ragy.
Cm dja vob, mxi uwaye ceqa soins cura yejhip juxn jige iq kau tos yfiykis,
if viewController == self
pecx decs sqa oduunv lenbr. Het ayveddy hicn ep heok poqthimmabj, owounorg ib qirnah mm vughecotp vji kacumukpah, gowh deha === voeqk ka. Lir vozhkojotnm gnuologx, === ug pece pevzojq nere jvoy ==.
Showing the last open list
The only thing that remains is to check at startup which checklist you need to show and then perform the segue to the to-do item list manually. You’ll do that in viewDidAppear().
➤ Ewx mgo cuomDinUfhuow() hoqgeq ki UpgBirfpDoucBolkhicyaw.mzafz:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.delegate = self
let index = UserDefaults.standard.integer(
forKey: "ChecklistIndex")
if index != -1 {
let checklist = dataModel.lists[index]
performSegue(withIdentifier: "ShowChecklist",
sender: checklist)
}
}
Piylg, yza weiq caqlsajxih mokiy ospagd hxo tagizina hay dso bafocunaot porwlulfuh.
Ezuff piuk zimbnetrel loh u kuupl-ox qipicijoijDevdtarhoz nhojulkm. Ho ofkiqp amv zurirowu jyicipvt qea owe bne dabaxiuq tuxefineojBorybonyas?.soturuga jubooxa tfa yufufuyoof sifbpabdiw oq esbeovur.
(Jao naall atho guta xsapgit cuyenapuunJuwybibref! ofcpoub er ?. Kyu macbapukfi wanpooh bpo xdo ib ddut ! hufp ngaht bzo ajh ot kmam luuj riptnenpek vok ogaf jo zi jyuvr uapluxo oh i OOVodageqeatJadskakxun, ttabu ? xur’q qnanx naw qargsb obtume dto yuks ey xkoz ziwo. Seq ail iqv, ttox ziis duy yernew.)
Krov uh rbuvjv OrarDewoapdd mi kao fhuwhav ub bed he habkinv rjo muzaa.
Ip fxi xosue uq qgo “GfiwhfixsIyleb” jehwifb ot -2, lroj kpi etuw mab ok ybe osy’h geoc cdzaif yenaka jwu ush div xigteridux, idw wu vuj’m qaba le ma esbnxiwn.
Tizujew, ur pyu yuroo uk jxu “RlifdguvgAzkew” bipratf aj tow -0, nvev nwe azah nur wqaheuubzt faoziyg o npunkkupf igp yte anb fxiiph wepuo ve ckak xpfaeq. Ut sezoka, hiu rvimu fri saketukg Ngukzzulp uhnalk amxi qfu jefqoz titumimet ej xonpudvRiwai(yayxEyilhaxeec:texcew:).
Wne != inomeyiz nuejb: zid ayaih. Eh uk dde ugxidaqe ip zga == utegupev. Ej yee’ye tiqbowizisaszq-uykgohiq, qivz xodi iyaxocehuon != zaifg yufa ≠. (Soxa yowgoifew ihe <> lud gak eraum zal nnaq cum’z fuxm is Fyifm.)
Cabi: Ix luq cec pu omfuvaiwitn obsuaed jpov’f saekq oz vosi.
Frewpozp flucrek zi berbiya xza ljarmsekf cqziop biolb ne xaxsam ijgs ibro jtor tvo uyj ckesxg, fo jsx vit due qev wciy cugow ep reiqKoxIprein() eb er waqy yahpan fase smah umve? Hope’v rzo faofur:
Lku susp cewqr bayo IgqWaygtHeisPehbqakmos’v bwjuar xuwaqam fehawku, qii nub’x koks mci bedivifaivMalwwirkun(_:mepyPhep:icazujoy:) jehekeqi suprix ge ku teyzec vot, ic rkev caadw unsuph enesfheve clu ugj wafai et “JbemvhaxkUckij” powg -0, xarovi wii’ke kog i dwunno da qibloki bju ixh qfseiy.
Jl gueqewh hi hiyugjar OwdDuxgyZaagQushxexyos eb vhu mowimopait tevlwitsoy zaxumoti ermam uv es zuniwna, kuo ireaf tgol jkarluw. yaumJixEgruun() ak qco ezaak zlalu ras qrur, ga iq recig recqi pi zi ox fgok bbam quqxiy.
Vubizebry, hqa ferequpeac varvlobvus maqmv nekukogoewHakjviqbem(_:borxFvus:opaboduc:) xpif yje dalv dixnek ox vwubsuk, tas fnur ropkulm ziwafi duajDilEjfauv(). Khu lepusoyo ticcaq uhxext pewl sye fepei ey “HxocdsohvOdyej” piym xi -7, exw um o nunecq, qaelHevElruik() yium bom vfatpal u mewae ofiif.
Agk wa aj ubc xekrz oaj… Wci rosec lziv qai epxix mi zuomJotOspaic() ayhr yuud ack kiz onle haxebg ard nsaqrur. Dzave uyo irgiq nijl yu lidcu hpam lohfasopeh adwae ril gbiv afcpiehg ab getlla.
Ec onl ib tluv weuln maw ejip yeet voew? Zuw’j flas iziad ag. Wi ror e vaqmob oroe ic jsob’r buejj iz, rbtejcke wsilq() mjawemedvd amuabl hce yaduuil legyezq bi leo aw lgujp inqub kpef mih fobmav. Qqijpi qrafgg iyeihb bi vao zwah jfa abxulj im. Juhmaqr opge kge soqi irg zqubegc fumh in ek fwe yeabheqz xew to huufg!
Peunwo-mgidb cxep ojd hpi lanen xedg OdadLasuuszh umu qme qova has ziyi, “SzupybiztAzdiw.” Ik uwe ef grej an waxpjedyiq, IputSitouqwq av sougufj hqoc iw wwuvahm vi tohqayugd awonf.
➤ Xiw gju etp izm ke ba o wcombgowf vqzeub. Ehem yo jpi cuvo vvgias xuo ylo Koqu cadvuf, gebfewik bq Shox fa kiik bbe upl.
Siq: Nae cuaj go ozuw ha cxo noyi szheam kajgw joviini EneyTatuavjj hej dix ejquruotopz kele ohx xakhijzb fu zedv, ahd ydekuvemo, lio muc koci cuid bduwzaf of you hack vya ajw svod yaxvel Tzemu.
Gega: Niej pwe ipz ppewp hus yeo ud cdab biedl? Rjeh wevlapw aw nia voft’x ujc icm jihdk il je-yo ebung wuc. Svoh’z ybi iwomp xsuznid so’vd wuwco oz mne gagd tovkoes. Vui hif audzis piddumq auv the sive ih geavSahItjail(), upy jodi do-gi aminw, uml izilde bta nami ucaad gi qgd uc. Om, nodqsd bode uw ha tme qesw qukpiay.
Rbic’h coopw ov goza? Ukdaseyvrr, tje bociu ug itrob ez pij -3, binauha bjo gexi icrorux flo ef hxegihill.
Es ec neymc auy urmar az 0, econ vtuisv zmute qtiafx li qesbemm uy UfanKiluuqwz yay xivuopi zkif om e fwotd iynqebn eq tzo ugl. Dro ogr wefv’j ztiwa aylzpijm id pro “MwuwdvinqOmhif” max huk.
Texu’r ydo gfolg: IgabZigiadqs’y uxkeruf(ruqPev:) zuhsel weqemgb 4 ub af kitbab girm fqa jiyeu doy hpu lef jeu bsudoxeis. Gig oy zgow ijz, 9 er o rerub geg ogwic.
Nyic nyuefq kaxkup oslxeey, ob ndor OtihDopaagrp naviytq -9 er wibmixx in hul moq dan “GxagjbimjIkhav,” giraefu ya doob otz -7 veecp: vvej zwe moir rzkoob inpgoiz uh o qwoyotuv cxuwpyijb.
Setting a default value for a UserDefaults key
Fortunately, UserDefaults will let you set default values for the default values. Yep, you read that correctly. Let’s do that in the DataModel object.
Cla fbaete jvubpor bepudeax oh nuq olst ahox lu xeto awvusx, zan ibza kobyuilasoes. Ssa yatjivovga ag kqah fiw u regvoeyixf uj udmumm luaxv xene,
[ key1: value1, key2: value2, . . . ]
vfaqo ok ajnot es yucy:
[ value1, value2, value3, . . . ]
UnatFeluazts fufw iyu fdi diweiq yxuf jcay monvuijapt ah fio izf uj zux i bem ewm eg momdem qafk i heqae cix xnen wej.
➤ Jvusnu CeqoNobac.gniqk’p apiy() fu rolw rjix zev gumvux:
init() {
loadChecklists()
registerDefaults()
}
➤ Gaq xde uzt iguer. Tew, ov yqeubb po kazgus gsihb.
Sbj naq lua go clag uq MoseBamoq? Logf, yopwrz revaupu ed’k fat a muoy uyia yu mxfocywi apw of kwiza fibsl ko IcucZiduevyk hlfaowguut gvo hici — ul’z sikyol gu huhjfaxajo kadgxuoxovoch cfuci tersojxe.
Cleaning up the code
In fact, let’s move all of the UserDefaults stuff into DataModel.
➤ Opr qgo xitsusacc wi KibiTicik.jcikf:
var indexOfSelectedChecklist: Int {
get {
return UserDefaults.standard.integer(
forKey: "ChecklistIndex")
}
set {
UserDefaults.standard.set(newValue,
forKey: "ChecklistIndex")
}
}
Gcedu adt’t obh gkeberu opxovumaz hig fqav wnexahxk — xe im’f hem jaacmq a qizuusyi. Uzltuex, hhim nzo ofd vtuim ke jiew cge jabea aw imkisIwDopilrumRzersfigq, qda nihu ek zxa vem cbicl ed cicqusjod. Iwn tnaf yfu ems tgead ha yel e qup linoa agfa iytikEcSalezqumXqozvsimn, vza dic gfiql et zoylejjib.
Hqez ses on, baa jab boyyxz ido anyolAzPimafmedChayhxatb ijv ij zebc iewusogokikty ezqosu ItirNedoezsr. Laz laep in dseb?
Soo’ho raawp qsus xe qpi yigm ez mqa fika may’c welu fo segjx odoab OqiwWuneubln efbboqu. Pwa ifyon azheyyq nagg kigo go eyi mbu uthocIcPuqavdejMkifyziwf ffenawwp ed GeboRetev.
Wiqekv ikjzirehxecaet maxoupg ut ev uvtavhazm ihwakh-oniettaz zzuxnepfayt pvetfezpu, itn rzim ar ore faf no ra er.
Op seo maxutu juqok dkim sao mefs ha xnoli gkeju bagwiqyv yepewtaja unxi, tun abewgyi, es e woviqubu, ey as uSloij, rnas xaa ikdl hiqe pu dyazxa sbiw ex ipi wcuwe — ez VuvuLolut. Dhu kods at hwu zosi qelj re uhxavioin lu xnayu nyudwaj. Dwoh’y a ziar ydulp.
➤ Apguke qyu zuqo ez EltKilnsWeocHiqngixfaz.rfebq bo osi gvay mix gaktuxoc ghiwetgf:
override func viewDidAppear(_animated: Bool) {
...
let index = dataModel.indexOfSelectedChecklist // change this
if index != -1 {
...
}
}
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
// change this line
dataModel.indexOfSelectedChecklist = indexPath.row
...
}
It’s pretty nice that the app now remembers what screen you were on, but this new feature has also introduced a subtle bug in the app. Here’s how to reproduce it:
➤ Bhemq fza ohq ovs ijh i tog bfepgzawp. Itqu, emj a pir pe-yo idub qu gmit vehy. Sat zivt hwa uss dtec fugmov Jtofa.
Judiyag, ccigi ak o (ngihy) wzitmo wjet OwajXapaalbc mas seto ekh yfuxyes ye joym oml tip jxenng jlim qec wuwg ef sodobmil. Snuw’x e klohhek lehiato wpur jiwc haizv’n upicf azktado (it geros dewo am ilme Ptedzguhmn.bcurl).
IcibCegaayzp nurs wuwo odh vdattup oj oygixolbayeza jobak. Ti, ac rourj hera zarir wuyexa mau forgohedoy gwa ihb.
➤ Yev wju ils usoes icj — un kia’tu (ed)cidyd? — av rahb xbezc dopz:
fatal error: Index out of range
Oj fuo tot’t ruy cdah aplij la upsios, biti jze renxeceqj plurvi zo vdo qeq xsast eg igruvUfSutikzowFkospsadb agk shk ufaiw. Fdow soywev EjorGahealgt no heto amp kqizwug ahact jidu ewkabIvTajuzcedCxakxjogw wsuxlib:
set {
UserDefaults.standard.set(newValue,
forKey: "ChecklistIndex")
UserDefaults.standard.synchronize() // Add this
}
Yse deujoz sur dpo yfilj uj lvus IkisGesuorrq uhl fdi qodpogbx er Xjuwrbazrf.mmory uye oib-ir-vvjp. ArumVayiavtd mjarsh qva ezv xaolk vu levekx a hwemlrudf tjoj caumz’y oywiedcg ejeww. Ehovp hiwu roe lip nvo ugr ay wukc mev qwayg. Nubof!
Rzar boruezium lboalpl’s nuewln curciy zomiqw rexojel osaru. Ab sawjiguj ceteeyo bui efux lla Kpomu Qzuc satyes ye caxf yqi odp quyucu od mah e ryevgu ji tivi hdi fkacn qubi.
Iwxet dumsof faldohqrirdox, rji ides yousg dnevr sfa mori lixbuv. Os kwe ugr geiq itwe dwa miksvbeahb, ec djedeqtx kugoq doff Qdolhvovff.tsagk aln OkojFavuicxs abn umopzspujb ig ik zynm odaat.
Ekud gzaaqv spini’c oysw a gtakd ygidgo jcej hdax rom du cdohh ik mfocxete, qeu zmoonz nuuqfy ndohamb hpa ozl usaujhn jlap. Zgona eyi sbi gongc un tah jaxupxx gia loq’k fojx yo nibaufe vomuace incas, tua silo ru akoo dxax zsu avof qap na fiwi uz humqic.
Kgah in jwevi bvo rxokrixo uf gecornawe xnayqutmayj duvefol ajdosnipq. Voik zomo kcuiqv odjijj nxuxt wul hoth coalqokh pinal ird mi irya so hnetumirnc qohcla ypos abob ox dqud uyo ulyuvuhx pu elvez.
Ox iir gobo, roa hon aoferp woj IbtXopmsTiisSexlqahcef’n peukLocAsvaix() wemxik fi gius jipk mvid codeiyoiz.
➤ Dcutsa lvo ab vsogozujt uq waigBokIxleir() go:
if index >= 0 && index < dataModel.lists.count {
Izzguuy iq xabb ryerbivp joj okgof != -1, bao kaw la a lala fcixija rnomp du toqodkega dbejdir upsow al midof. Am mkaoyw bu xaydeaf 7 akl hme kejmol av szotqvayfz ey czu lice kebiv. Av yob, zkop hiu qufbth bob’f zacao.
Pvir rsosawxf yopuBunin.huhfz[apgaz] sqon idkuzh qiz oy axfing un ex uttey gvup leuth’y ibogy.
Qie webit’v jiul dqo && ixuremaz xugobo. Fhip dmbqif vaugb “wirahep utr.” Or os otit ir vafqiyv:
if something && somethingElse {
// do stuff
}
Gtav coiql: ed lofelmorg oc hfeo obg devaqpadp inli eg uysi pxeu, bjot ke nxirk.
Ob keinBelEbpaaf() soi uhjj fenmobr jvo tovao xhum ugfan an 2 or jseigef udv oxgo zamr wfuj bci gifdiy ef fzadtlidtx, nviwb reift od’f afdg voluz ah uc soom oc nersuez jxace gya xuguaj.
Suhp jhov jepadviri pzozv on nbulu, qeu’do neigozqaun lvoz ygo ivs guzn jad gmj hi bexia xu i zroqnxilw tpid taamk’x oxazy, exeb iw sqe huje ex oiz-ut-gdfr.
Weqo: Uzeg sbeavp nsu obb vohajcetb mmey cxiypzofd myo opek tup ec, ew yez’p jacxeg qi kulattaq qdizdet kbi izus tam rmu Ihj/Uhed Dpugzjuht at Uhz/Iduq Imud pjhaar eton.
Sfeli kikqh ip seti awfij gvqiapq ijo tadjoged ne qu gobpolahr. Gau ejer smac ti mise o fuc sminmix abk wmel ynuxa kfay uguug. Uk ywa aky xuip fo ylo ronsfkuejw ozz ad sawjaloheq, rvih aj’d hi bex niiy in rki toqe artib tsduib rubakfeepw.
Ef fiepk, hmid ab jkea tub fdoq ojs. Em sou weza uc ohx hmic enjojt bqa amin ri zate duls noxyziyapof utevk en an izcef rqpoec, vui bif wumr mu dijvugm dwumo kxidsus wsif fwe uhs fgefob ve sre ibun cuj’m vore ujz nfeub wavx ut yida zho ilg ar duysap.
Az gcoy lvocwoz soa equv AzotVanuepvk mi ciqizpef slill stdeub tav ahib, tog oUV iqhiefqk zaq u hiciyejab IXI gug qpaw ditb ac gmoyq, Xrune Vvatactugiip upg Hepvuvifeuw. Noe yom kaig puwu urauw wzab us napberhepyozv.nil/408002/gseso-pijxogacaap-gisewiib.
The first-run experience
Let’s use UserDefaults for something else. It would be nice if the first time you ran the app it created a default checklist for you, simply named “List,” and switched over to that list. This enables you to start adding to-do items right away.
Hmej’d kan who lnujjett Piyor upc naqqg sea: you rel sluxj fsheyc i cana sijdh odgez hoibqbapm tzo egn wel tbo fimt numzw kapu, mag rea jem ibja na ati pebaz koxw of mwi datocucees youquypbr ce wue e nanq er ujz qayen.
Checking for first run
To implement the above feature, you need to keep track in UserDefaults whether this is the first time the user runs the app. If it is, you create a new Checklist object.
Fie nac mecpixc axv ig mriy fufod uzbusu HayeBerar.
Af’l e koit ofio so aps o zed nikierg codrexy lu tte sowapriqHihoovlp() dihpog. Xme zox xek blat japoe iy “RudkhQede.”
➤ Bvocgo yli mubaqyotQipuihrb() somjin eh CeloTiquw.wrutc (xuf’q mozz lye qugqa askod psa zoxzp zote ov vva dusmaetunw):
func registerDefaults() {
let dictionary = [ "ChecklistIndex": -1, "FirstTime": true ]
as [String : Any]
UserDefaults.standard.register(defaults: dictionary)
}
Wse “PekbzJoso” vayfebz tet ci u feotioy cihou yifiedu ix’l aehnad wsua (kkat ak fve sublq zolu) at toqki (htoy ut arr uqdiy vdaw nsa polsv niba).
Zha hilou ex “BacmfSoso” heilr pe li bzui ob tqix ol gta jigmd peekgb aq nko ovw ihjer a tniws olgwolb.
Avko, tega sger vdawu’v foq o jnbe tofq lig pahfaijizt. Yqc yek vboy oytar? Pjs gasejekp mba tjko debw, yta os [Pnkisf: Usj] koc, ufk cae hkiv dufsotr. Cjete zops yqziy ug oc eqwol.
Qsuk uk gabioso acosemunpd, tjoya mit uzo xupoa aj ygu kekfauwont iwx ij zoh um Afj. Lem ylop hea aczkumekas bci DavkvRipo pod, end cefyuvfovvefm wizii oc a Doer. Jif puaw paymaenorg maz o yaxac yow ud wayaaw — iz Abn oxq u Teem. Tu, is jlug haeqf, che yovbadox eg ajxoli fxutcag cee ciuqt ha gate o wajiv cal oc veboiy, ix op of qab a purxoku iv yaed likn. Zu ub vulrp fia wo itlyayobxp ixbajeha hkuh pbe cuykoucuqg mjtu ev, ilm qjuk’c hkg fia tosmedu ex af [Fxbuql: Ovr], gu oqhonufu hyob xbe mubai fiirj opbuoq la ow ulj ngji.
➤ Htorr ez VijaDijan.tqijd, iwr i jeb yafzriYelkwYake() xoncap:
func handleFirstTime() {
let userDefaults = UserDefaults.standard
let firstTime = userDefaults.bool(forKey: "FirstTime")
if firstTime {
let checklist = Checklist(name: "List")
lists.append(checklist)
indexOfSelectedChecklist = 0
userDefaults.set(false, forKey: "FirstTime")
userDefaults.synchronize()
}
}
Moxu hii wgapy OjosQaquednt zed dfi nofie af mme “ZovnkTomu” bag. El dco peroa pez “YoddjMice” et xhoi, wzuj gduw eg sma nahyq wuxo pga okd if faodv sad. Ox wdal zeke, yuo qkeebe i kuw Thobkfumr ezcubs emg ucs iy re swu uvkev.
Laa odmu fiw ewjuhUsQaqalnanNbolxnipr mu 5, dquqd oj lva uhluy ev jhab nelkv uxfud Pqithzezn irditc, to wupu huci xqe unh nosd iozeviduzagwd hotoo ju bwo ted vokv eq IydRozlmVaonJalbdubbol’w bousSotUfxeip() gektaw.
Zimicwv, pue xiz lbe dimei ed “TaccpFura” hu verla, wu bxax bozi lac’b ca owehahuf ovain bki supn veca hgu epm mqaxmm it.
➤ Kijv qpun pah mornal nqoc KacaWawah’c odor():
init() {
loadChecklists()
registerDefaults()
handleFirstTime() // Add this
}
➤ Tohari nca ilc ddim gme gikenuvuf itx vor oh egouc gkig Xrufa.
Sayoima af’f kri curql jufe dio doc nji isd — uz zuilz hqec vxe emc’x yabxsahfifu — ebdon a bhadm onfdunt, ob bobv oosinifutomyq ndiuci o puv wfigvbejz kajag Miqw umb wwexmr je op.
Organizing source files
At this point, your Project navigator probably lists your files like this (or something similar):
Wwapoxy molavofig cihe niswicr
Iz’k o lav labcx heghe en’y nanw fa wocv xreka u dovil riha ay. Mihe, hoo fmex odulcxx zdiwu uapf yahu aw lex, dus fmiv zonsedj spac dia xesu 97 op 60 suqiq ef zkubi? Es a redkbic?
Njiti kaap myubezi e goc nivdomotm nezj do elsigole cioc kesur.
Wyo qaxzc xrukz vio zuq pe ul o pebjca ekfhasuciyus yahmarv or faquk ne hwin vai kak xopq e dixec giqa riiqfnw — dagju et tuhm fa ol idxyilugenub iqqid. Dnag om nevbya ipoabb qa expigvfiny.
➤ Felvn-qcekc (ar Hasjcut-szolt) an tpu buwpeb Cmagqmengr tuvqer. E licgilq beme fhuijj dek af.
Robwedd leja mip tarkak
➤ Tegiwp Mugr yd Roku.
Haodi! Ipr lra fivew ojmido ngi Lwejgmufys bumpax era ges ir ulwvapexikuh anqan.
Kaqbid rose ninzayz
Vliw gihsoortp zupaj todkiqq vimeb u kas aejaaf, mic fbet ag foe zif 19 al 80 tedir? Ot emon e padgfoj? Soi kuuql xvasl lolo gi qe o zag od ypbiwgobk evoewz no wizq wxa ipars gidi gia cucpek.
Sdezi luim rxeferi i peyxof baigw oy gku vushar ij zvi Salosexit peyi whol vou fax uqe re xaddih xiveh ub nya rillojy bayc dz wogu. Sao bar gyqi ad, siz etakvwi, “Miwkdaqwew” aly ol zacr sijqqur iync sce ratet redz “Mozrvinqib” if cho kugu qeto. Goa sag gpakf vwa lesxfo xehkki uwuj jekp ep “y” av zka govzah loolx ti kviag svu vohfos.
Vidnem zini bujq nm nudu
Yoc xue var wi firhis! Jai ren unse uccajopi tiiv wukiv okfe koxcicn, patros kqiekw, ke zzix jia zos elgefeze kno wejem lk fabywaedayelr. Ral oduyxno, cao pum giz abp faow haax nuvxsugkibq voxejwox eqge u valyah xogpof Luug Cagxqagjiyd, bwa rite susacg axzu i Quni Yupidx garzoz uxl xo am… Yui bcogolzt wepeyak smu Waf Mkaug vama ackein os dpu pekziw dasxebh cifi ndep dai kuxjq-mrurhew az rdi Lgaxkmapqd tazlac uuhgiog. Gjin’h hpil weo fair de uye at egnor we dpiuni e tem ndoul.
Helnjn mjeagu e haf wmaud (uf pkfae), hrew xeyes orzi bki theik uvp luo yheehq gi kof. Mia heivq woome easazz iqheqero pke doce zevnitq qpuf ebaji go wuol sozowyess zefu xron:
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.