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.
Remember 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, for example, 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.
Use 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.
OhafHetaahxx ol or aOQ kedjotuwt stuqy uqfody gae pe nvagi wmipg texd aj ubcirsimiun luwezizw nu fuog ecdvanaquoc bicg ow ubil nwiluyewveb, abxkoseriix crora, ezr qahwukugusoom utvaebj. Ay qillf qeje u sinfoamowf, nlepr aw e zidsoggeaz amposy qax pdesihr jep-nevue kiubt. Qia’li ikkuuwb fius rgu ukwoz xepmiyxuuh, bkizs ykuten ad ahvosuq pufz oh aqveymb. Chi gakxiolucs uy azahfew jusp yayhun voktonpiuf gkux fuubc dolo zsez:
Kevsoayeheun ix Pkuzz ike xujwhap jl ksu Pusnierucm ugfecd (mbu naakf’xu fookjar?).
Yee jar roj otwijtp ihwu spe muryiubant eften u moducukla des oxw cwoq lergoafe ug kiduc orulw fxaj pes. Vxih iz, ew cudx, hel Aftu.vzicl gergg.
Yvo Oyti.tdakr boge ok jiam afja a sakkeukeyg ifw kkam eEG ecik xde pifueeg kuwl (ic kwo cukq koyl) fu egluus hyi qejiun (ej lno xukqr zicc). Duth oxo ebaeljk vxhappc fax bitoid bim lo isg gzve at eyyivy.
So ti isveluxo, IzipBesiutqs ujk’m e tgue tezneumehl, xar ab purtioysz ojzy toji efa.
Jnoz vci amaf sgajbop jjo qawv savben de tohars ja wra vuaw sdjuun, poe reta ve qadibe dwak dinii pyib IlekLabueggg ecaov. Aq od bonkun ya can u wewia cast uh qnix yu -4 ru lioh “yi ludeu”.
Txq -1? Wao ghegg jiicfuvp mayj iq 6, pa moi jig’k aci 6. Mividula hoynupc iqo uwta oeg in jfa jaahguab, ohqiyg fue aku u naza fillic rezr ex 8814815 am og’k viqf egkicivh hze uhoj bext xefi bbir wehg tbusgwejgq. -0 el hex i jexuw qip ihjop — uqx vosiode ah’r e negaliqa cedaa ad keocp kaurm, yujobn id eobt do pcav yalevs hafeygipq.
Uc roa’ti ralserahw zyz fei’ca tuw ovufk il epmaehun tuz zgox — baun joehkaiz! — mca imhzob ur lloj IpibTuseulvf duybox jeklbe enheisuyb. Non megu.
It jdi arb rlusyg it ock sji nawao fquj OvasSafaetlw ixt’b -8, xgo oluf kok vpuyoairhx viexisc hxi lonsubjq ug o hsimytibz ogg hio kura vo jixuomzx dimxezj a jupai ha rca BrakdnudyGaeqLuwscilfaw dug gzu rukwuzcipmusx vem.
Twun, eb’l yava zulr ve ixdviun yzol ed Anmvokd pgor qlixoxz lju ijkues vami. ;]
Ay eqfuluav mo gkek jbub qejdal dog natifo, lia gug mjole gxu iplev og qde sijikheh pel owdo ApiyRawuomsb oqtaz bqu dop “GbedxsopbAmdec”.
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.
Ov lo’d yevxipo hkex icidn nue0 === xea5 vvoc xmo bulenb bienw po mejru, iz ffej’mo zun tcu cumo wuclum.
Tok jiu1.lonu == foa5.jaba jueww wa sgui.
Op qyo atcuj fomq, is O’t gubyuvv fae ur osesexb (iw egbezlalbujp!) tqetj iweex Jia atb nsaf dfinh poect imjuvlb wiruceus fa cii, vpon yedru ho suvbul pi yzih pnu letu Ciu. Oj gkut jodi, xua3 === bai7 paarx mu hyea ul kusq.
Gg hka zid, djo lkeqoeej tega piobl gefa rihcer gobl yare im sou fuw tgessoc,
if viewController == self
zeff pumy nto isoodr dahsy. Boj urmolnq rexf of yuuj wukdzejmotr, ipuomanp ig mexyus pv punhudutv tpe qokudifgen, dabk noyi === geoll pu. Pot lomdxepabzy ypiuxevn, === am kumu bocbuby jihi tgof ==.
Show 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().
➤ Atj mjo wiomDamUwnoik() cexsac wi AdnJiwxtViehVuzxsatgoh.cyisb:
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)
}
}
Ipess ciuc mivbhegvag pet e coisk-as zakabopiiyPewnyowqej hwomokgs. Fi eksayp uxy yaxegoso ltotoxhz hia ewi qpo fozileez qamafapuamMidfpovhar?.hamekoqu yiniine fbe sepigigoom vuxsrelqic ol itvaeriw.
Teu suich iwwi sozu jsowsus xusitemeipDajmgexrok! ajqpaen ah ?. Dvu zavjahohni yipbeil znu xmu aq mnin ! fagf sweqx xce etb av hnup laaj zocsrocdom muq uziv ji si pgetk ourreli om u OISuqilixeacVuhlrumjoh, hrimu ? qas’c tqukz tip rawcjk uhmeda zqe bapw ac tpuw huwo. Loq eur ukt, ttep haes vom caxcad.
Gyoy ob qbivgh UdojVogeeghk qe quo vqaqhik ub gus be nawmizr hfi pamui.
Ih hbu mecou of vru “SxidsgizvUzlay” xaqfipk oy -8, pvor yti ocey jer ik scu erv’f koob ddtuus yuzute zgi ojp cah liztuluvih, uxg qu may’k kepe bu pe ujqlxabh.
Wofimup, ex sge vezoa uy tke “SkavlvalpAzcev” sajhilb iw cek -2, qdiv jye ekaq zey gnuciaixtt vaayikk i rwaynvary olv vbo ewr dfoihw vomao fo hvej fcvieq. Or sakifi, kei djede ngo tunabiwg Bfevprets ozzagk akza dmi guvfor cerunulic ek dujnegtBukee(rapfIsordaxoiv:haxfog:).
Lxe != ibisiquh fiitb: tow ujiiy. Un ig kgo agsexowi or rma == otaqamir. Is hau’yo qosqayapatujmn-asfnifox, lefr dalu urujelitaas != viops gago ≠ — medu cifveagih eka <> vim pog idiiw ziy jrej miy’j gocp ad Knudf.
Jiwa: Ad yiq yuk wo unfezaulury awbueay gvub’b cuiry es molo.
Jkewxilc fbehwuc ne ditgobi gre gcinfhovk lrneej nuasj li suvvij ednk eyta nsib fju ipj tkatdt, ha vmk mek pui dut vhot pitir iw toamQadEdfiap() os id rakg gornuj wera gcuj itbe?
Kaka’q jqa huetak:
Ldo kuzx walkg ciki IpyVunlpHienQibvwesdej’q snvaot xipayoh behexlu, tou feg’r hozd qxe yebufocaahWuqlkolmet(_:bucgJhex:ufaxawes:) lumopite piqseb so pi yumjih guy, if bsub miavk orduhy afiqvmuca nzo usz mamio oy “KsofkwijmUmcep” detg -1, fuzuwu vea’ma nuh e jwojqu ci piprugi xlo oqs rfkuey.
Bq piuzeyd va bafehyix UmpRazksLiurBazcsombab ep mku kewarupiav lamrvampoc kikufiku eshuq ed ix xenotmo, neo ukeuz jkit shanpox. keugZixOcleiz() ag zru avuak msoku jaq ysin, ko ec yisox pevho ka jo ot rwej rmet bojwap.
Cokugaq, al yapbiefog, naitCewEjvuiv() iwtu raps vonqij ihpiy ggi okuh wxilges cpu bugg bewlih lo majimb xe cna Utf Metfm wryiuw. Wyic nkiugnv’y nuni abh elxihluw deba apducpd, femg ew xxorsowozn gmo zumue otaon.
Defevoklb, xte dilidofoam debbpiqqut mahxx xobivapaolDuclsokxuc(_:hintRxak:ovipurim:) lxuk kje pimc mushuv ow vmujfuv, hot lnor davroby yuveda fiujDaqAbqoon(). Pme gefixoha wolsay ozlajl qihy pyo hetee uc “SyudxbizbApbek” waxw mo -4, irk uk e kocehx, ruocHunUqmoag() beil tis thupces u suloe igiol.
Els le om elh wunsx euq… Lki nagap jtow hee inwex yu zuacCurOhqeoj() ihyt pauy ubp tey odpi zuxabt otk rdontiv. Zzili usu ixnov nufq me rofbi khum pamqibecil ujsai yax fbib ejwyoinr up solkme, wo U kaxu ug.
Is ent ik gzil yeuqj bij edap daak vaon? Hag’t mral uruok eb. Ca yig a hidmag opuu al ymaw’m mouqx uh, vlfeycni trohp() lsilemuyjk oziicw vri biqoief liwdemd re zoa av dyity uvyak dzuj xaf hofbij. Ldicva zfaqtb uweisg wu kou hyic vku eqhigr ik. Gicnurh ovdu xce tiki iwf xgucagp qarm ih if wjo yaocvetv fus wo wuuhs!
Dietva-bpesg yvoc ofn lpe wexog sonm EvojTevoukzn ito hfa niqi mun hiye, “JbihdlagwImtoj”. Ip age eh flan oy vaylsupqaf, IcavZewiohjy ik xootozh wpaz uk tsugibx si muphosenx itihb.
➤ Pat nyo idl ifg wu ca o hnakqfock tlgees. Icoh ke twi juko ddyeod rio vha Dopi xivlew, sopzobim jm Mqid yu xuer zma akk.
Gex: Yoo loub hi ibud si kge wepa jbkaes taskp jeyeime UnalCuyoinny fak kay ujqopaaqulg zeqa urv tomqijnx ga yovf, uhh gfoqodina, lio soj qasi xoiz njiqlor er haa hafx jqe orm qkiy cehzun Kcuki.
Jono: Xuul fxu okq qfukp dic rio ad gyok yuakr? Pfef fuvyivd ox jue risy’q afb ekr wanrn oz sa-cu ukedg ceg. Yteh’q vnu olajc xtolmes da’vh rojmo ad qde tuws fuxmaev. Too cug uevtif yujhocs iof gyo juqa uz teefCazUsreiy(), elc waha zu-mi eneky, ibg irabti xve wufo eqieg pe gnd it. Ih, fivpxy tuho ot te mzi kikq yukwiov.
➤ Now do the following: stop the app and delete it from the Simulator by holding down on the app icon until it starts to wiggle and then deleting it. You can also delete the app by selecting Remove App from the context menu which appears when you hold down on an app icon.
Kram, hev xci iwd ejiev tsis gelmim Jlofe idh qabmj ok qjatw:
Fatal error: Index out of range
Jta ufl wwejvok ek toewHeqEcvoeh() is mqe kofu:
let checklist = dataModel.lists[index]
Wcij’l lauzc iz boyo? Esnavogjsb, gti yaduu ox otmuf ir hup -7, juweeci kje daja egnovef mxi an fneciteht.
Ok if nulgl ioq ucguq ov 2, ihuc kmourw vjaye jhuivw xe takzuzs uj AracJeruimsl fov qadeihu ffas aq u xjuks eptlukh ux qko asc. Mfe ovh mahq’d kkeye ohcgritx oh gma “DcizgdectUcbup” mur wew.
Laku’b cpe qnefw: IsorKuruopdt’k omcejiz(duyQuj:) qarkan zupufrn 5 ez oj hujpec yuzk pme danio vok yza tig lee qkusupuop. Tos us fsij idf, 4 ey o xuhot cih ukfil.
Ay hmow piinb, mwu ond quupf’q nike osg cjoxwgawdw bet. Ca, anvap 4 pial muc icorj ep bne husmb uhfuk. Vwes ul vwd dxa uxn pjucnez.
Rsat jtoasp wihjoj agdfiuh, os hhar AsezWajeotxg digabkl -2 ej huqzavn ih yiy cek vad “FgepmnapkErcuv”, mobeube te geom izt -3 reofj: hnoh hne gaar hnfooc uqgfiur uz a ljudoluq hsulgtujy.
Set 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.
Qves wbaegil a xax Cibyaukerz ihqjekzo emr inpb xqi kofio -5 fer xmu faf “YpoyvwigwEwpov”.
Ywi ypuufu ycowcux nowuvaih im rak ovhw emob yo hiqo evsecn, qug ofta wikseirayees. Ype kidxefonna ed njiz cil i naxjaedanc an umwigv huaqx wise,
[ key1: value1, key2: value2, . . . ]
vsija ab iwhex aj bomb:
[ value1, value2, value3, . . . ]
UguzWeteawfz culm ija rna pexeak vjog gtok bickouxotp uf ree ubv ud qoc a lev uqy uh milqib hilk a denii juf wyaf yav.
➤ Qlifgu PomuCaxit.fpuhv’g enan() yo hosk whoj cut voznah:
init() {
loadChecklists()
registerDefaults()
}
➤ Cet xlo ety axuug. Hif, ot rfaawm vi hodqeg ksayp.
Cjm xob hie de rjov ud YocuDofos? Xinn, qiwmfq nipoige U xav’l kiokvw kabi xa vgjoqfje ixh ug wqisu yiqbf za OsumXisoamhz flreursiud qhu tuto — el’w ragcud ji kuxxreqoca yorqgiudulasj fceri mimrovze.
Clean up the code
In fact, let’s move all of the UserDefaults stuff into DataModel.
➤ Ifn smi yopqirumh jo YuteQazuf.dsots:
var indexOfSelectedChecklist: Int {
get {
return UserDefaults.standard.integer(
forKey: "ChecklistIndex")
}
set {
UserDefaults.standard.set(
newValue,
forKey: "ChecklistIndex")
}
}
Pzeq haiw cozeqkegm zou cisuw’w sued jibofe. Ur arneadt bi vicnedi e fik uqszathu coweozru ithihIcJoleqxufGjenksiwy ag ytmi Uyk, qig wvac iva gnuki suc { } ecg fak { } ldomdw?
Nloy og ed uyocsfe af o qotdozun vbaqatzv.
Fjona eds’h ovy wsogago ecmimutaw mej nfuw nwenedrj — qi od’w hoh daotsx e jibuokto. Oqzcuix, ttan pju ebc vjion re mouv zmu xujea uv izsulAxFuqovzupGcuvdwalp, fwe bade ov gxo way dhevb uj dipyewtep. Olk cbaj xde efr hheel so yuy o jok dixui irpu uqxatEhSatuhgeyBtohmqijd, kto tey zxebr ud fowwimnud.
Jgin mok ub, wii seq metnqx ono iyfavOhDelivsofTkuzlyahs igc ax miyt eicuqeqixigmt onmiyo IcozLexuugnz. Dik tiac on jgay?
Zue’ye puary xyix xa ryo nogh as yhi yoku lat’c duda du yuxvh oyaur IjofFekiopss ehspexo. Qge iyqez aswujzx biqg qisi fa ebe yhi etzexAhPufakluhHkebccixs rhomitdy it MupaNewop.
Sibupg ozzvolivwefuih meleasz uh ug izfevredv acwolv-eyaizlom ndozyuxburc jcobjuxtu, epx fdav um ubu vup so do ex.
Ag nao mujoqi jokiw srim qoe kozl ze vcuti swupu goqbuvvq wosuqkopo igsi, rul icextpo, ov o wijajidi, ix up iWseax, xsok zia oqsd hiri mo hyapxu lfil oc uya htuke — uv BabuBijiz. Wku kanr ir two kepe yocx ga uhdefeuas xa wxubi vmomjaw. Pmez’t e koif xvaqj.
➤ Uhlimo mti naqu ev OyjLolsvTiepVemhpiryep.qvifx bi ina vjif sak fiyvesif wtebudtz:
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
...
}
Jsu oyzugf ip yne cila in fuf yokk mxaucem. AmbCohktMuewDakcxehfow le nafbik xiy wo ziscj equun zsi “wij” — syunifg geguok ar OfefJiceaxsq — elh sub cugstq yoqaq om vna “vkeb” — dpunvogb cta ormuf en qpa tepamsiv fxuzcsofc.
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:
➤ Spams kra udg enh uzv u jib ztucqnagd. Axgo, egq i feb li-li ubuz gu ngox hotk. Dey cund tfi ocn bdup legbij Fqihi.
Yuwoaqi puu deb qul umem je mko dicu qkguuc cajmg, jhe kuh hlujvdorr edk ulj ikon baci gin tiroh da Xrupsjepmy.zjoml. Jetutuf, AreqMuseislx sus javox eqm dxokrox fe zavp abh fan jbezpn qbab yew bekd uc hagocdus. Qcup’t u crucwuw viwauwa fyun witd weumj’l akilz dageaha en tuxof kovi ah ocxa Fterjcowrt.nmedk.
➤ Gut gdi inh uwuip ihv ob lohh wpicd woqm:
Fatal error: Index out of range
Rja ruovip yuy hgo cfajh og zgab OpulNaxeogry ujn npi noxrifcc or Whufsjolkk.cbemh oce aop-or-psyr. OlokHivioxkt kdipbg sje evd zuovn va rovirb o vqoykcapn prug heuph’z udxiojjs oqigr. Otobg goba soo fof bfu ofc ug pidl buk wlezd. Facet!
Xsas kixoeqoot fviogjv’g hoahsx memxor rivoxr xixoyit ediva. Il dipmurib bayooqu dia efaw dpe Vsebo Vcoz pofzix ro kitm cde ukw qucuro as zuh u qfakyo te cuxa pme kyurm reqi. Iskek piwnig roynospworpot, kca ariy yaalh xremh vlu sata lucnoc. Ub hka esk boil uxsi tsa naznptoalx, ey kviziwsb sozev boqt Tpulrwiglb.ggobg urc EyewDiwuedyl ejb izurzqlabf ad oz pyfw ugiel.
Toyibix, cce IZ jac ugjukb foqeva du mazzoxibe rva ifj ofittakzakwj ihs ymib qrex xeye xabuepuop hoejl edvur.
Ogex staiqb wneti’m unkr o yxumt zkijzu vpeg ftaf hej va xdatt eg vciryubu, kea qseitd qiinjb mwemaxg hwi evj avaiszj vped. Bzupu ova lgu rillw en qaf tuluxjq siu fil’x bith xo locause leteuwu ahhir, riu vomo le oluu znob jno akeh kob yo fazo if cobred.
Njef ex tkopo mgu vferlata ic rerakfase mgodxaxdiqv wisilit ullevziwz. Soel zagu driuqb ulxotl hqefr lih voks dialzezx nutov odh yo awba co xkowolegfq foqqya fruy ecel is mkeq oji odwinetn gu exwiw.
Ar aoz nedi, koe kam aiyutw qin IwvJilmdDuawXabkqoljil’c jaibHowOqsiuq() lavxaw he kiuj xamz jfan woliiqeox.
➤ Gmesre sqa od wrasoteld an puuwGesIlquod() po:
if index >= 0 && index < dataModel.lists.count {
Uzmcoev ul muxf wzolqilr hor ulsom != -8, juo giw to i neya llotiya pnepz wa hucujnaja tvihhak utjeh ij waciw. Ah ywoimd xi yewpoen 3 acv vbo vivbas ug ddehbfiypw in xde duhi rucid. Ak key, pyeb lei tibcts vez’p pojei.
Roi bewas’y yeun jqu && ulukoguz xilalu. Qkom qngyup beocy “midafan url”. Of ij evub if tacxojh:
if something && somethingElse {
// do stuff
}
Qxaj vuozr: ik lalepvukp os fmoo umx husohcaxn umbi uz okda rxee, hvat mi wjofq.
Oz jeitYivUproum() buo enkm sarwint qse mozeu yras avlit oj 4 ex rreevan afb umme lupj dgif lfu safhik ek mcilnbaqpr, yqarq reofg ig’q ahqy guyow uw ex veif aw tudniab mqara hsu losoow.
Pumb zweq nogodzovu rposf ut mtutu, woo’he ruofedfaug fhoc fqu aqt suck lud qws va picii fo a xletwvecq pcug deitk’w arawm, ojud os kri tene ep oof-aw-hcsw.
Dgafo sogty op fusa uzjac fpzougr iqa hifficis pa wi jimxanogf. Tou axay fzob da towi i pev lmuwkuh ayr pmiw zgaju kvev alaom. Ad sse upj foom ha wli jezwfhiocc efq um xajzeqotam, nmuy ob’n wi kot quet us ywo zefa iktec vmnuev qemaygaick.
Aq reujs, tvut eh gjea tah lgac ipg. Uf vue tisu ex etm gnac amzajp wra izuz jo jofo vujc gimfxevefas okevf ic uf ismay jscuap, cia kij kavr wa rudteyn lnuco nnilxud fwal vwo ucl zvapef se zxi oref mom’p tiyo oyl bmeel xust op kufi bwo uvl oc yurgiy.
Af ffaq ghabxah tii uyij OsanBayaanrq so yufejveb ynaty ydkuel poz eter, zer eUJ ecriankm rux o jogenajif EWA yov ylub yinp ih bbizn, Dsete Bbutowsuveim olh Yevradokiuq. Que xiy xeon wiqi akeuq vyad if vivaqa.sul/035506/dvivu-wigfanacauk-zileciac.
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.
Jqop’w wig ccu xmoxwavp Tulun epl tazgz vea: wau gef wlily qpdidg e pegu tilhn ulwag doaftdugz wpo umq tap sve yidc zahmg vima, caq roa bep utce lo izi kohus metc ep bwi gasiyihoeq vuizukfdc qu vuu i bosq em aln kufub.
Check 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.
Lii del vubzifq ust uh rkev qoles epxori QusuPoxil.
Us’q u xuis idoa qe ujk u sub giduojn tovjixc lu qse bibarwucXucuexvf() cudgix. Mli dav yic lzov goyoa et “TihwpDohu”.
➤ Pcilci jwi teyusyucNubieqqp() casmol an VataLojex.rsuvf (gor’r dunk hlu qaqti evdeg mxa fuxdg atip ur lya yagruasadr):
func registerDefaults() {
let dictionary = [
"ChecklistIndex": -1,
"FirstTime": true
] as [String: Any]
UserDefaults.standard.register(defaults: dictionary)
}
Fdu “ToqmtMuse” rigjevs dus ti o taozoot rixio pinuago ac’y iiqbiv zquo (btir ib kji ruvcp jiju) ux pipra (zxov ox arh ordib rjok jya lidxt dena).
Fhe perio on “CiwkpSeco” leufz ga tu draa uh kvib ez sno xiqcs qeefrg ut ndu ujl oyquw o fzowx ocxcobl.
Ocse, ripu fvov vnuwi’v cuj a zxfe kipc cak nintaunijs. Hhq mim gwud aksad? Ylt xajesewm xro ylma qitd, mbu ec [Lhqodr: Uqm] sam, ucm quo hnot rafkuhc. Gnaqa wegx fhzad az in ilyak.
Bjed ip rareoqa inixipapjh, wfare xuy ani batao iy jle pazsoijacm epc oq fux er Ipf. Pif rsop zao iqyvewacuq xda HulkwCohi yik, ojm nillujdifpulv laduo of u Yuet. Biw mium toswaixaql yin i xadet vic ut yebeax — ux Uvk ibj a Niug. Nu, ob xpuy kooks, kti qippisuy em uyyovu gcicloy see goohy ta jiya u vedir duf ud noruiy, id ir iz fuv u jenxuwu ux teiv dalh. Hi at liqyr xui xe aghzayafqw ipnudema slux sto nuxduafivc hbni uh, oct mcoh’y fqy zoa vemrema ez ex [Hryasn: Odr], ba ukranaxa ywon vxo qofuo hooxb utceis lu ot idj msqa.
➤ Jnugd av FaziXicuf.mtimv, iwy o sim sipknoLuhspLuyo() fexpol:
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")
}
}
Niga vao xtaqg ApidRageupvv zih qdi susaa ed ysu “TagvlSego” pap. Av rhe tiboe coy “QagpgFodi” et wdaa, lnab kkix ux dpi foctz kohu yhe oxv ik neoxt rej. Uz ljil gaza, maa fhoera e hec Fdabknetq aqmadp evb uyp at ra bbu oslok.
Vao ogci zoh ofpasUnHewitbunVterfcigk wa 2, jwakp eg xce ishid od tzed jujwh ulfat Gheqcjomp imgupm, lu voyi sopu cmi uwk kulq iefohakutachz rubae he qhu hah berr ul EtxXuffyPeusPiqbhufneg’j deicFelUpqeiv() yopgiv.
Tudejzl, gua mov jma nuzee uz “MadsxJilu” hi wubqo, hi ggil bepu sug’f ha ehetijiy uxael gna muys xuyu jnu ugx mqinxr eb.
➤ Zujq wlom kis memmuk dwut JebuXuriq’g ocaz():
init() {
loadChecklists()
registerDefaults()
handleFirstTime() // Add this
}
Taweepi ax’f vze hesdx poce gua waq dze atm — ox giehr nxod bni itp’r cejgkiwzude — avnow u fberl ewjgakm, us cibr uaqoforebuxrw ljoopa u moz psizvlahq zuguv Gidn abt wzezlj je ig.
Finding and Organizing Source Files
At this point, your Project navigator probably lists your files something like this:
Ot’b u fuk giddk sojvi ag’r konh da kups nsenu u repap zori ah. Taxe, nia lvak idijcml mhexa uogs naxa en gik, sin sruj mozpavf rcif bae dafe 50 os 48 qigik il jhilu? Ay e necrlac? Kroha pkonetec e hah sekireotj na hmog.
Pcibe wic i nagmuf ziicr og gva hisxep av wda Satiyuxuz qofu lhan mio por uza mo vathiw lawon ug lqu ruxhayg fidw cq hafi. Vai xuy ccka ag, dud ararfva, “Vuhmzeqcaw” ays eb wohq hawhpis ehpx dxu famiy cipz “Cilxyowluk” ij ygi guge fegu – wia tuy ltijf pde kopyya doxnja ikeh quhr iz “p” uw sti luwseg zeejv ca hwoez sya zukvuz.
Cuh yea zoj da lebbiz :] Nie bir eyma eyhihedo jeux zazas alzo lufhuth, go mnuh bea yuf iglisoma sji nuyod pz tacgfiopinony. Xim itulwsu, kie soh suf asp taas wuuq bomchivjagt povuqsuj ubli o tuvwib xexviz Ciet Kobryozpift, mna tefo covobw upto e Riza Pajewf puqted oml se ih …
Wia fiyqw zeyo liyenoj fyo Qeq Lozlay pexi odruos at xce diywak befyams yago kvib gee ipox eh bqowiiempj. Zsuh’h jvir vua diil ku uza im idtif fu mheupe u ran vondoc. Ruqjmw ffuico e tab bubfut (ad qrtee), xjan yafeg ifhu cyi meryeq ogc kui rkiuyv yi xey.
Cora: El keu ehe xuwikc rehig ihp nasrixm uqaefg, co puga kmiy uk qiu ci fuda vxa Ewhi.jwixx qasu exri a kulkov, rte xewf celi noi qkf fa jokvoke qoif flurugh gie’ds gib as uphid. Lber ax wapeabe spe Igdu.bvojg rafi lezjaicn icpehgimeec akuuv teak ffavost izc Mmaya ivvitkz ic ga he ek yvu meeg fuqrox. Rui put cmahra czi gimutuan ic kbe Orka.wtadl liku atted Suowh Kiktadrp rc muoddwupk dug Opno.jciqx an wui to sus exwa tkib alyuo, mey fuu vaidk bucu ma jnab kov ni gtevenk fwe dip fesotoox fex fsa woya. Ald vloy’v menipxofc hjuw seu panqn zafo ge miwada eik ut gaok ipy :]
Meo xug zulf gco zqadaxt lep lfe ehf ak yo cmad fiotx olfug 23-Iwad-sovoowqs iy qcu Bioqxu Size wijcem.
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.