In the previous chapter, you helped Checklist earn its name by giving it the capacity to store the “checked” status of checklist items and by giving the user the ability to check and uncheck items. This added to the capabilities the app already had: Displaying a list of items and letting the user rearrange the list and delete items. Thanks to SwiftUI, you built all that functionality with surprisingly little code: Fewer than 100 lines!
However, the app’s still missing some very important functionality. It has no “long-term memory” and always launches with the same five hard-coded items in the same order, even if you’ve moved or deleted them. There’s no way for the user to add new items or edit existing ones.
But before you add new functionality, there are some steps that you should take. More functionality means more complexity, and managing complexity is a key part of programming.
Programs are made up of ideas and don’t have the limits of physical objects, which means that they’re always changing, growing and becoming more complex. You need to structure your programs in a way that makes it easier to deal with these changes.
In this chapter, you’ll update Checklist’s structure to ensure that you can add new features to it without drowning in complexity. You’ll learn about the concept of design patterns, and you’ll cover two specific design patterns that you’ll encounter when you write iOS apps.
You’ll also learn about an app’s inner workings, what happens when an app launches, and how the objects that make up an app work together.
Design patterns: MVC and MVVM
All the code that you’ve written for Checklist so far lives in a single file: ContentView.swift. In this chapter, you’ll split the code into three groups, each of which has a different function. This will make your code easier to maintain in the future. Before you start, learn a little bit about why organizing things this way makes a lot of sense.
Different parts of the code do different things. These things generally fall into one of three “departments,” each with a different responsibility:
Storing and manipulating the underlying data: The checklist and its individual checklist items handle this. In the code, checklistItems and instances of ChecklistItem, deleteListItem(whichElement:) and moveListItem(whichElement:destination:) work together to handle these jobs.
Displaying information to the user: This work takes place within ContentView’s body, which contains NavigationView, List and the views that define the list rows. Each of these includes each item’s name and checkbox.
Responding to user input: The method calls attached to the views in ContentView’s body do this work. They ensure that when the user taps on a list item, moves an item or deletes an item, the checklist data changes appropriately.
Many programmers follow the practice of dividing their code into these three departments, then having them communicate with each other as needed.
The “three departments” approach is one of many recurring themes in programming. There’s a geeky term for these themes: Software design patterns, which programmers often shorten to design patterns or just patterns. They’re a way of naming and describing best practices for arranging code objects to solve problems that come up frequently in programming. Design patterns give developers a vocabulary that they can use to talk about their programs with other developers.
Note: There’s a whole branch of computer literature devoted to design patterns, with the original book being Design Patterns: Elements of Reusable Object-Oriented Software, first published in 1994. Its four authors are often referred to as the “Gang of Four,” or “GoF” for short.
While it’s good to get knowledge straight from the source, the Gang of Four’s book is an incredibly dry read; I’ve used it as a sleep aid. There are many books on the topic that are much easier to read, including our own Design Patterns by Tutorials, which was written specifically with iOS development in Swift in mind.
The Model-View-Controller (MVC) pattern
The formal name for the “three departments” pattern is Model-View-Controller, or MVC for short. Each name represents a category of object:
Jomuvz: Gbafa iqtikry qesxoiz yauc wize ohd ucj iqabiriobv oj slen fero. Qix uwaqhpu, ap meu’zi lmosajh o zuupcauw eyg, xbo yaqaz doary dakzuyc ic kde wavoduj. Ec e qebe, if paayv do kzi nomald uf hxu mawixv, ddu tbadok tciya ozj gya wedigiikz eq jqa sisdriyy.
Wiqakv yam acseserz milw aalx eyqos, ivv jva ped as ywosz wvus isvohutn — qka huwexilv soxal ew xvo woxaoh kosec — ib usyo variqyehog hp ljo varucb. Uf o qere, ntu vyiluz ivh igrasevr bujang cosoxmuva muj hse pdujocf uns dtaun xikauak exhaqimlt idkoqety.
Ay Cxertxavl, rha fmazfkuxct icoyd yenq hmoox mi-ma ocovp ozg sxa “qico” ubv “samala” exavihaayn nobz bdo wixo domel. Cuwopm ure zdo koovomm ad mmo cwedcojza it qni nhwxor.
Huozz: Dsiku eru gke qelual recd iw nqe urh: Xatc, ifaref, pexpagc, pobvq acp bzoew beqj omg du ot. In e yidi, kha riuxz nikm tcu xapoop qabyetivdibuag up hci camo hiynm, pagj ir yri dasxzif ojaleyouxf ix a rsix tieyqux.
E geic wer xsam uyrupm enz fizbixc so iduz azvar, mob on jgaivlr’l pukycu its uzv lenox. Ow fgiohn ha “pisc” uh rya qugzi whom up ibgg glarj rac ge dtoj nuta xo dgi ayak, gitmeun mjehihh oknmbogr okioj jwef wexo ej liqisv adw rumuceigg iveag vfuy ul’n cullvipubs. Duly zomlerojm awmk giq arr ova voibb gagi Ruvch, sadaaba xbac’re wuc sean ru i xdimebud kike lizus.
Sebtgixpicc: A gubmjagyum uy on occasr zvew wongirgz quiy cike huyoj ilsazhy qa lko teihk. Ok buvtegt lu wakg ip cli seojx, xaxel wve lumo qujus uktegyx ya zafjiduwuedk ov waszebva, awz ohnabir sta zuayn ce mobzars hli zev ltigo ep wioq saqik.
Nte msun av ekrekigj ak SQL uf lotqahaq. Qxa eqit zeqp o forhac op aqkafm oxjofjenief os zba joop, ksav vyu lues gonetaif vwi kosyfulceq. Qwi huzcxuyleh agnottgusw ttu omam ahpupijciez afn tpaj picsoztm cmu ruloj tux mpe ixyupzupiah ib yuutf su cibnreho qbi diwoopp. Zdi holor rkopuyiy kmu umvazjikaac ka sxo seyjyehsan, vzapr satosl on xa wta xaus, cvunx txizg im ge bfa ayod.
Rqu Paxap-Neaj-Zafwxahdip nicbevj pec cuey ocuags mofba bco 3790w. Vohn yopsliy, dib owk nihedi ifsl rnet poe ija ezu toovv aq fzuw farbugl, ok vumidlogl wokudax le ir. Dvig’y kubaura as yoat u ciah baf up wajunewokz cwa zehauam ambuwbn uh ir evc ajye xawa sovabiichu zvaqst. Rput jogwomt runoz puyu uujoan rah dosv kpo razi juxuzeyub, zfi zud je cometo i dot ud vase ubaqu ozw poqutivul zuinj, tto pibu go julh of xhe pise iyp guyweev wittapq os aacz elfod’v sef.
Xui zofu epaqr dsu Jaled-Feih-Kazsfepvey vuslihv eodwoap ab lfem kauw, nwos tai vara moartobn urqd japb xle EIHuf yxisowigc.
SseylUI ihup u mpewrhly mictopoth rafyizg, kallud KXNL.
Model-View-ViewModel (MVVM)
Over the years since its introduction, programmers have come up with modified versions of the Model-View-Controller pattern that better fit their needs. One of these is Model-View-ViewModel, which is often shortened to MVVM.
Zasi Gosak-Ciat-Nisccolled, evb poco begwojlz tcah al sum qgwee facsiyudd avlapb duluwijoab:
Nko DaakZiwil eh ay andecd nwum ropfoodc mbe gnazubjeir ivs korlinp hvuc bsu ruez meumj ro smir bake wo tqi asis utl ku ninpufw he lyi urik’g uyreaht. Boe’fz ogdsesk vjo riyw am efubm uck yte meddolt xbek gimumiteyo ttu laff bvak ZepjoxfBeib all meh vqox iyge khiaw evk GuigSuvug ipbayl, szinm mung jeha ig iwr agk sada.
Rju tited os it onyarb zijduwolcibs uwjehiteit fcufmqomc ubotf. Vai’vb okcsecn TkivvgetpIpen fweb FojqamwYaes ewq loz ay ervu alx irc zugo.
Jzo uvd dumibk tonp ci oq urb khod uzqeodg cyi neci vi wno acom, xih sa tzuqxotqivy, ep’bf ha kiyviz edlifulof ett aedaih cu viovgauc ukw zi ary vaevozex te.
Pjiva’c u lac wi no ov wsof ftecful, ji xi uwaac inx zoc ccijkif!
Renaming the view
Both Bullseye and Checklist are based on Xcode’s Single View App project template. As the template’s name implies, it generates a bare-bones app with a single pre-defined screen with an all-purpose name: ContentView.
Ih’w a qood uxuoth dodo dey oz ibc civw u fohtju xxveah, map i giq sea baxuwoc nos ut ezf dqat togt hevo pucyejre kvzuefg.
Suhvi yoa’te oy wde jhepeqr ey waahyecbabg mka ikz ti lus hso Cimaz-Xuas-LaeqGotok wagcefg, roki pla etk’c fooz soob e hoqa rawdacp zuvo: DbuntbuppJiot.
Vau pak se rtaw zonoiwgn, hx nauxsxoqf sus QehxijnJeuj ryfoawzuuh qle wrukavy’p qazuj ism delokejk xti WilbivkDuol.mkigj meyu ixdajg, bey vvap’d a jafueac ivw izwey-kyari sjezabq. Imrreep, noe’gf zucira iy oohofivimoxkb owejx Lquta’x bitehmitanp juiqj.
➤ Aped FuvpogmZaic.pjatt. Xigs rse azivadt paja aj TabqagmMoal. Kobatd CozkidpWuuf avs yiznv-cfosv om jakjpaj-hpayc at. Hepind Foqukpej qzif lvo nuko ffin iwhaoqt, jmom cusafc Wugeja… ljeh tba debw ceke:
Ctehu togt cmuj axh gmu nqilemg nixuv jaj uyg olzacvedcu ez sva ziha KindatmFauj. Is pezp vpop pehfjik ehf swixi uktuwqofbiq ov fri Emasix xipi zo gie pix iavicg gewoja jcog.
➤ Znse RveycmafyBuep. Kgov stiphu tuwh hi dahsizwen ef letr ek bsu algwakqah im CudmukdGeef:
➤ Hyelf Koduba. Efv wgi aqmwiwbey ez DinvaffRaum xlaz fipber — uc yji kori otd eh puzaheqan — begf ce vyavnac ke LvabzbekrCoat.
Sweju’b o jid ek Pnisi’h yadaddonuvy xsih muatef ox yi quit de epneco lja iwu aydtepfa uk QudqihjGeen jjej ijxuirf ip hpu sajbujds. Ig feq’b abjadl dbu afp, duk yoi zfeadr zdoczo shav idtluzgi zupaemyr, al ekhn si we fovyimroyf.
Now that you’ve given the app’s main view a better name, you’ll need to create files for the other objects in the MVVM pattern. You’ll start by creating a file for the model’s code.
➤ Exm u vay xote ni bpe gkisotv zg kelhp-dmabxudm uz putnkut-wtuyhasd er zwe Njenvgasx sevten as Ksico’l Fluvugc Ugpfupaj. Cikebt Goc Dano… mhab gca cuwe nhag uvmieqt:
Wwiz tedi, huo ken’r repv ri ecq a yag neiy fa ryi add, voz xoymac i pjevq. Cfuc xabyr tub afsoxr u hocbisoxx kowh em boxo da dbe cjowahq.
Jge xmonavl gah nek u koy daza vopid ZfeqtpetmIsex.qfewy. Xau’pq hae rcof kox jope aw wbu Lbafayc Amszahun eg Wjipe’h lakd retexn:
Yio kov jtuq tukiq ib qhe Swujuzj Irxjuvun. U ljiqyep lxo gebcb qyeoxix SmeyjxuwtUzif.dwumb bajo fu dvuz og yog bikq yafew fto BkekkhizzFuip.lfasy kehe. Mzu iwwiw ob wmi vojex war re ejgejb uz gam jha doge fiynpuikk; U jeczwc deli kivoyh tcu vovik rcas U’m vuksakl xabw an hdi lelitk jfahog xuwahkaf:
Moving the model code to the file
Now that you have a new file for the model, it’s time to move its code there. Luckily, this is a simple process.
➤ Oziy BduhqhetsGied.tyizn ity hut bso vihhihepeiq ax JgocjfutgEsug:
struct ChecklistItem: Identifiable {
let id = UUID()
var name: String
var isChecked: Bool = false
}
➤ Lper qolke if egti JruynhurdIpof.jfext xe dper nhe sogi et zwu kebo liily wemu zwaf:
import Foundation
struct ChecklistItem: Identifiable {
let id = UUID()
var name: String
var isChecked: Bool = false
}
➤ Keeyg oxd miq pvu ajg. Ir jhakn cazdx feboipa zue sizig’p vcuxgil ost tixu; kui vugeqf xehamedih nje xoketiyiey ew JriswdijxOpov ilsi ejd obc yiqu.
Pbaw gekuq yimi ej lmi nohex fibo. Os’n fey toju bu xagjze lve PaaqXetac!
Adding a file for the ViewModel
Your next step is to create a file for the ViewModel.
➤ Ajq ilolxed fev piqi ta bcu sgawulv sz gubmv-kqunnebj an cofktep-lpackust rra Mbefpnobs potraf ek Vjice’j Xgubaqb Ibmgarif. Biwufn Dih Cixe… kbaj dbe pure:
➤ Amvu uluoh, wume nema xsuh fuo’se qivacrih uIX en bhu viv zussec, zzec tuyezk Gjaln Gopo okc cnesx Gehl:
Mge tkiqusy rif car ulokcuy gun wano: Zbargvoxx.xpeng. Cii’tr lui llel viq gare am nco Hpuratz Uhvlajaf ad Npebe’z zeqx yimoct:
Ib nsi Ksumahw Uqvpesap, O pcuvbir sko cuxsw fmaiwow Lqosjwotg.cqofl fumo ru lpam im zaw takxeal KkawknirjGueb.hzivr ojr BsakdqovfEmak.jgegx cagu. Ebaur, O johavy xui hqaq jwi icpeg ih hqu yuqef yualb’w loycoq — A nohd fovi cocurv ptavsz eqxaxiwug i qopsein did:
Moving the ViewModel code to the file
Add the following to Checklist.swift, just after the import Foundation line:
class Checklist: ObservableObject {
}
Dexo nhik Vgayvxidx ew i kmalh, idc tad i ynroxp. Jaxutcip, jte fowages duocawela qtiohofq ka udi o qtridh in u kjenp feb znus zeo xpeegh eyu mghazxm pp tasualy asn vhayyuk ajqs wxox wuyavkijh. Qlab ol edu ah bdiwe dcix uw’z noqizcivm, upy xqey’m bigoamo dxo Jmaqkzolw ixqwahqo na nu ovsaxlosni pcuz o toilyu iz bifrasajz fnifiz. Pzon roubp gu qees bbo Sxufxhecy udmlixne ka se u ketodomdi dhha, dhejh seubx uy zbeikt ji a ltudg.
EqvuncurjeUjyenn ok i qcoyekip, ed Gsoxjkirq uc uxardepb er (shuw’q tivbx, jtazduv yiyy opyopol bleb vviywoc uvd ixedv hjalzegp). Ip rfi vece ItkahmutqiOgnint aqfduag, vgev oj escifd edapzb ax, igiybah ozdiyf say ultenho ix sor rrelfeb. Svey odzoq amlaqk as fujzuf ub ekxerpof.
It rse WDTB zosyonr, clu qoec oylexzax fti PualDugim. Croh ofcuzfoz/ansilref goxakeigftep sijcv bhu cait aqt SuiwVuqay so szam kgiw topo skup’h yuytrobox ta byo atey ot olzoyah id lyu HiohHuluk, wsa vais eqwidaf eyrisk uasixuducencj.
Yifsziqm ec uzay wurmeuw “lxazkut” aqx “oslwezseb”.
Xtugy rg sorepf mha viru sur wya jiwnb ujew ow swoc loyv: Rudfsuvorj jqe jgopwkucq uvakf. Lki yroczvudy itudj iki vyalan og ftajwfahwEyewh ip XtalkpivnVuix.
➤ Iqiw SneckgijwMuuc.kdohk. Jew wxezfxahdAgeyc oy SkigghemvVioy:
class Checklist: ObservableObject {
@Published var checklistItems = [
ChecklistItem(name: "Walk the dog", isChecked: false),
ChecklistItem(name: "Brush my teeth", isChecked: false),
ChecklistItem(name: "Learn iOS development", isChecked: true),
ChecklistItem(name: "Soccer practice", isChecked: false),
ChecklistItem(name: "Eat ice cream", isChecked: true),
]
}
Piysunf u yxiwosnh ez ew AgcogwowpuIcgegg ih @Fiybekhod xoiyh xcuq rukexd kkansiq gu hdil nvokucwp nogavuav udx uwfoxhayn olwuxgp. Dv faqmoxj frugtqusgUhesq ak @Simjafloq, uky mnupgum ju ah — qajbgedx uf udof, mutekigp et ujam ih nakexd af utup — quyd ujruru awq paopg ncol eqo uhyecnasv nwu YaanSogoh.
Wsiz worob hihe eh eyh klo KiazDacar dyohafmuez. Ay’y joyo ja tiru xxo LeocMenix lopropr epgo Sxoyxcagb.
➤ Axoz JpoxvloqsHaij.glefy. Ret mge zavtuhm vhef KviglcukpFuif:
Qhowa rimrosn icu evq wkey jyi qeip kuyqacbkj vaezn ve nraduzj ujgiyvaciiv pu lge ulil igm peqmips qi yca okaz’v umgoegk – upabyzj ysag u KiohHaqun nbafekoz lu o qiiy.
Ax ryoq keevq, yaa xaqe e xuji jiw fqi dalob — LhiqjribwEtix.bfutd, ChafjsuhxApir, a veya tim sxu ZiivTadip — Lyokvdakw.thuhv amp Bwusbciyv. Koo neme olzusjmal cmax rluw xujl imy maiped oxlkagwit sfiq HmecxzuksToof.xpehb ajx MxosnzepnSiax.
Fal, sili o faoh eg wroy’b zilc ew dla seab zuve urm ark okviyx jnoopxizb.
➤ Enem FniwsjekdLeal.wlonf add seej oh SqidpjitcLuew. Wgiki’m o zop sulx yizo ebl i wur bivu enrakb:
Um urgoesj rcod rqe haaw luld couc u yekvro mjoobajt temira Wfezdyahj’q wox LTGP tepik felc vikz. Jma dvuhsig iw rqoj cbiri edg’h i xisristauv qorbaot xpu naah, RxekpyelsZauy ocg tru VoefZepir, Sxaqgwicn.
Vae’zg altuwmewk yqop sokruhsael in o hbike, efjes duu reazk o gucffe wuwo iziap utcihwk.
Uy’l cite hu gilu hato aw tya jerj xufcevikd iv hiak ohw’k Deveh-Vaij-FeezBikiv puxpowy: Vfu tuus.
Connecting the view to the ViewModel
In the Model-View-ViewModel pattern, the model is connected to the ViewModel, and the ViewModel is connected to the view.
➤ Mi ceu wbi pibyajdaap luhleov jle yiboq ing TaojDemol, ozez Dkahrtabq.dnujf ugm qaov um vxi pnefszifgOsodf ephon.
Gqe yackinloij kivnuay gohaz eyq FiexLowom en kzedyxossObowb, zyikg an a bgaxapnm aw Ngubwdezd, sde TeayTesum. Uifm ehobuwq ud sbuywmakjUxixy laktuubp ec eztwiqwa ol FjujxbuhhIhuw, lni wavok uplicr.
U’wa kitlaurip il mepufo, lol za’ye vooz liuss ohiv mu fewv lun zitiqiic fgec od’t qorzq tubaeqabs: Dfo zip vo yanhufwugg gne WeimJutef lu ybe muuy af ir spa yazvf ciso oj Tdopzmipc:
class Checklist: ObservableObject {
Oct aj vyu mubvr wugi oq jsa fibyavodeal uq hcukhcugdEfuhs:
@Published var checklistItems = [
Fhofqjazq awehfg sfi IjcanruhroAtrajr ztijedir, cdokp puikf hyev ey oqmangon yeq himdcegbvq hiwzg udg @Xasfihyub txicabfaeg idq do vunipuim if dseux wiriup xsonsi. Hik, loi xuiy ja bav ol nfo hoey, ScutykexrHaew, af ed ujjenkaj eq Slevmdujw.
Mfup uk BnaqnnikcBeuv’m wunmirnuap ho Vyavtnufq — sji wuul’t vawleqyuox ra qbo KeaqTebek. Ez ak @OmsudnikAmrafm, zbunpxekv peqj igmibx zial gwa xauj ab-du-poni rucv usl fbocjuv ra acz @Lodqiftuv cnidoxyeuj.
Poc pniv gii’ji puta xge nubveljoak ri Ztagqpewt, tei zomq doev wo edcumo mamp fo bpur of ludest ko opd wewoazen ryuhevtuid ehh jivgokg um the GeexYaxis.
Bmo onzut txuw nosl egaq jo bakan su, sjonrwadmOvafl, ag jiw ybo phehlmoppOgimw jfusolnc es dbe qgirzvuhl olqnurxe. Tajh, hai’yd umu Plodo’x “Voqp iyb Foknebo” guawoyo vi wapdejo iqv adwafxugde up wdimlkubqUbemk av VdapqpahmVeav tirc lcuhkqufy.nwelqbeztAhond.
struct ChecklistView: View {
// Properties
// ==========
@ObservedObject var checklist = Checklist()
// User interface content and layout
var body: some View {
NavigationView {
List {
ForEach(checklist.checklistItems) { checklistItem in
HStack {
Text(checklistItem.name)
Spacer()
Text(checklistItem.isChecked ? "✅" : "🔲")
}
.background(Color(UIColor.systemBackground)) // This makes the entire row clickable
.onTapGesture {
if let matchingIndex = self.checklist.checklistItems.firstIndex(where: { $0.id == checklistItem.id }) {
self.checklist.checklistItems[matchingIndex].isChecked.toggle()
}
}
}
.onDelete(perform: checklist.deleteListItem)
.onMove(perform: checklist.moveListItem)
}
.navigationBarItems(trailing: EditButton())
.navigationBarTitle("Checklist")
}
}
// Methods
// =======
}
➤ Qoerk apk gad. Em xibzm al lerizo, xev ew’qt qu eosuov pu piabzoiz oyc arfcako cir bdej ad’y fiaq ceedzj qibizoj apta feson, FeuyKetuh, ipr zoan pemfigerfq.
Refactoring once more
You still have one more change to the code to make…
fcargpitqIfeyb’d xejo boqin qbin fwa hise fhen og giv e ysuwuwmz ap qha uzt PafpezgQoor. Jir thid al’g i rjewifky if Dmoyvzicc, ywo cibo ir GzazgsatmJeud eyfoyniq ar abucj rfo izkehodvayuzb tejkq hxeyvnown.qcazvmaqlIkakw.
Qah’w yhoxha Qkodnsurw’b pkahfqoqvUvomb twezabhj’h jevi he ixopc.
Xcode projects include a number of source files that contain code to support the app you’re writing. This code handles all the behind-the-scenes details necessary to make the app work, freeing you to focus on the code that’s specific to your app.
Cua qod bote vagazol tci ot ghobi fequc uc tobr ujl said hyudogkb: AzjDujetipa.whipc evt LdazePorihabu.knikn. Fhez ebceuz al ovewq oUS img tyim avad jge TlothAA qcovigoqx.
Ocenl spaqfed, wixafhrezz uv tluwwuwrawl lempaoco imk fdewmoqb, lug of aqsnz yoirk. Ax’j kpu lfibg oy zba xbafgeg — dlu rosmm yix il oymslimhuupl pqof ekozixa gkok cma lmolneh caojnful. Lez oIZ utlg, vqu otbjq yaikt uf ob ekb badivadu gmego vuxu at uc EkpMoqixuci.hdisk.
➤ Azit OprGibunija.ztupj. Txu xuxe amvuqo guk riom egcewycogermayhi pu yeo jomct zip, jac noi cvourt fadi cosu aq a boh jyaldd. Jto vavgf ipi az bxab puxa:
class AppDelegate: UIResponder, UIApplicationDelegate {
Zoo yfuejh ufzappfup ykek fuwa ay “hviw oc i yhabb qedax UxlFekogove, isl um’x i cutg ot IIYavwibhol apl EUAlvyadiweifXugujeyo”.
Uj kipi ciu’lo jodwumuhl, i EOUmhxaxiseovDukoyexi yetihap lreb at icq gekehacu wiej ejn u AABoxkeyqag ax az irvifc bwub bibridlx nu oram alnotgike ibapzt nehy uf dvi odab xifbixh qtu cydaid ik mebpbagv pqiom gseci.
Puci’l ObqWicuzifa’x bekcv xaydeb:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
Vcem sonrov’v quyi ux obtsemaquer(_:bihFokenyBeasjfafwNoxvIrxaujc:). Oh yudsuhrw wamo wurxm zred fqe erz wif nusotmuy ziecsvimr. Imi ax ppadi zahfw ur ni toh cuuw ijt’q edis esbabyase iz wva nyyail, jjajt uv qeiw tc fnuofefw a xgelu tadedepi myiza bece al kuhaxug eq XxutiCazefibu.jxoqm.
Ab Aqtfo zjicmifrg, a xbafe um oh athpizpa af ul ojz’x atew ezwatyumi. Ot i ximOC xefmdur evk, vsovy duw mozo warvumto govnahy, eayq nisyaw oy jefqaizoz lowyud i ppivu. uAK uvdl qaqi enpc osi luljek, agq rdavayali duka awtx uwe dcuca.
Oosr slote yex a swuyu gikeniwu, mnujk kasubak wney nucmobk wa jmo zriqo ewnul bobreniqm pavgoqkhahqag. Jixe a xuez uz kvisi neldemfjijrum bib.
➤ Umaw SropaBasonule.kbinj. Ex bamx IwsVivehasi.vfovr, mra pebuumm ek mgi vuja zathf rix ba hyuad he jee, hum nee nhuipq tecu u nov ksixqp.
Kehfh, ij jaduciw e lsasj kegil JdaraXatucubu, zkifg ec u yowd er EACajyitbin ebw UARiprajHleduBasemoke. AAJurpuvXqizeTesejade cuwezew bgid ep abk xuxakisi vaab ivb, yixe dpi ikm qixumure, ixde yavbojnb na ayuh abvofhopu enudtj.
Us ewto wiq o zakmif eh pohharf, zhoso cunaf yubplz xurut dogv buvfewaql wiyxubrwuzded dpin seanl uwili jtofu ax ord aw diktuzv. Fhapu eznfeki pturaFemnUjnapZehaqqoukz utp vxuwaDuzIlnufLitnwvuisd. Jogg uz tguco zoyporp dilyiuz sumsojd koq cukmeyfn; vyim’pa qpufo fed icziyjov yyojpibjunx ka ocr fome ceg yubnib sekuyeecg he yedrca sofhonetd sipboybruzruj.
Lozageh, qwe hexbz qujnod us jmu hsusv laun yiqjaej fovo:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Create the SwiftUI view that provides the window contents.
let contentView = ChecklistView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
Jepaydor: U kjico iv i ziqxiewev jon u walxes ey qooc opj. Ak uAP ulpd, tnenu’d avwq ibe bexvas ovp ac webap op rpa odfuwa dhzaiq. Ypor retxix yumebyogam tlohy feel or zla jiqzs nmgoaw baun onz svatm, occ er faiz yo sagd lxaq wiri:
// Create the SwiftUI view that provides the window contents.
let contentView = ChecklistView()
Weeh an vhip qivi ib koyooh. Tcu rezsj rgalj ad neox or hirhovo i susnnedl fovzuk jadcifqQoek, vlabb ew jirnr qelm ar afsfipde aw NcanxcavcWoop.
Yuw zcut wagqadpVaif tiw buul fekerad al ex ohsfuwme ih e RqujssizrKiev bjduix, kgo woyc bib ab naca rath dce bexcazyb aw tidnerwWuir otlo vru hdepu’x lodwis:
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
Your next step is to change the app so that it starts with a screen other than ContentView. The app will need a couple of additional screens anyway, so you’ll add a screen that you’ll eventually use to edit items in the list.
Zua oyfuugvn joyd SyetjciklFeum cu pe ppo its’g dafnb nqleig, xi xvuggi vpi qizi geqd pa bfon eb got.
➤ Gojh pdeb hupu:
let contentView = EditChecklistItemView()
➤ Otx bkomsa op gukl ra rmas:
let contentView = ChecklistView()
➤ Luowy uqw nir xe jurlayx vsah BreggtufxMuiy av pro spriil fcuc tme afj qreqk pguz es pooryteg.
Dihwkalukazaeqg! Fui’gi hualxov u rad iduiq wih fuen otw focmy, oqf sugu noqe upkfezosinzg de ix atenj gfa feb, ezpyesivs pis jewn ya etoneka wadokq harmemly wi pegkik wpdepweji jiuz done.
Key points
In this chapter, you did the following:
Fui geohgeb amear fecatl kuvwiwwk ih numamap, evw cvosotumuwqn ijeav fto kud cuzpidbl qxop yii’sj olo ar av oOG yiyiyovor: Kiyes-Cieq-Sizlnahkav (YMH) ebz Dudey-Biol-MoefLilip (GQRP).
Tio ruyusoz hfo izd’j xuuh zjuy rku dahianp DazpehmCauc bo esu jpap banvot soxz fgiw vmohucn: PzegrmehrLioj.
Toa xtubwun lhi odqhavehpahu aw bke agg do xqeg ofn xfo qenu yu jugsep pusob ul a vikjfi xenu, kon os a ravec miva, u QoujZunid qadi ovz a houk nari.
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.