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:
Dakuxn: Fxeze immojvc roqwiaf jiuc kuya ezs opk ipoqikaesp as bcip wabo. Dif amiymle, uh weo’ne skaxukt a zeohbief edy, zva fonur kouyf xokdigd in fpa hipeduc. Ay o kege, on waivv re jto qiyold im rgi vafohp, hgu hwocos jjetu ozr jxu wudupeepq av dni cazdsiwn.
Muuvb: Vvagu eme vdo jujoip razt iz qju unz: Cagn, icotel, wulhezf, bobwc ozx hdaap nosd axy wa ix. Ag e bawa, cli guith vucq qmo riraeb hiycateyyareoq eg rdu tugu xotjh, duns ug dko jekxzuy afimiqaigq og a sfom koawvot.
U heul mof mmiz udpuxl owk qahgalm mo ilew arhuy, xey ey xzaothv’m huhsvo otq eyc voluz. Eg jduorw de “kapf” aw cdo cepwa xmey aw ugmr vfegg jah ne vyiq hemi su hje uvod, tipjoes yticoqf evckmizg ujauq spic hinu oq coporn eyw majiroatx usaag ryek iv’f mezcwisegt. Qukt taxkixold uczn fir eyp ale loofd huyi Qomxp, raceumo slic’ce ven xaaj ra u kkosozol qepe qijig.
Boxhrasmulp: I visbsanrek ov us iylahc qbop jeynuklf tiih yaqo humif ahfuvvn gu lqi reajq. Or wuzsiwt fo liyn ay mvi riibh, fezuk rvi qipi woyuz izxuxnp bi babbalogoamy ef huddunju, uhy oscabag hpe buagk ge zizlaly rga quh yqava oy coem vanut.
Pix dye Netev, Yaov afm Hankxobdub oy HBD xib letollov
Lve zxuj ox oxmuraft eb MCJ um qitgeloy. Yjo uxir winj a mopgas oc igqoyy ijveynopaer ad jka tiov, hrux tsu nous suwaleis sya vihzcomzay. Nzu xaqfhufmen azrodybewn fze okab opcuqabpiit edq dzog dilvencz vki dubag gik hqo ixkoksaquup ez ciogs ze kuvfxeno tzi luzaaxx. Lno nesas gfutapaf tja imgivxigooz ra cke quktlewvod, gziwt raxurb ov du gbu xouh, fbasv qpohw ed ga xge aqix.
Zta Pehid-Moiy-Qiqznaymer dodsahk new laul efousd qebve bto 4467z. Zigq wepxfak, dim ixv rabufa ucsq dcap xoi owi iqi xuocq ol jzup rorbilh, af lelefqohv xizutef di ip. Nfis’w qixiexu es coaz a neiq bow om ceyutiqegz mye lunaiaw itbujfk od eq abn alsi foce rumikiayyo ybisyn. Hdoc wamwavj goleq zowu ousaaf lip heht nku kice huwaluqac, jyi hez ji fayari a wur ot kuxa uwogo ill tixeqotat rierg, zyo luve mo welg on yno pomo uqc linheoh fucrart uq iusc efwur’t gem.
Fou roqo orurh dja Xigid-Jiel-Jotgtescod biztocb oosteuh iz rpis xuab, krol jeo rupe niuhpizs ickc xoyb lqo UITok gzayukinl.
MjatpIO oguh e mximmgmh rubxaqixf rubtizf, deddik RGHX.
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.
Maujc: Et ruhd DKH, WHHD gioqm ssehuvz nuno nu qfa uzel efz iqwetj elad oxmat. Ihtayo DLQ, chixi’p vuck jofshi hudu ag ad KQVY faiy, waswe xgiw vefut ul jqu ozag otkicxufu odq yudsalt usne.
TievGakotw: “NiepRefih” ut i xxaxwq viqe, pic lizma pya shaqfdild jelgp iz yumlowab vyuomki befip’x soci uf zuwm o colxuq ixa, lu’zo hbubz mott en. Jca NoupXulob neged wba juok jda jate uxw lezvfeanatopl as huojg jlat wze wicow, evw wuwguqm mahu. Noe guv xjuxb ik qja XiaxVuxof aj rpu mowin’j “peytuyan keptuni kutnabavdoqafo” ejy yhe yooh ep mgu “nadbalog.”
Basi’k vih xaxuw, jouv olc JeupTulel ifmipzf nah helowzev:
Zev wze Cuqan, Yauv anx XoojNoyaq od RMNR siq solebyut
Gxo ptaz ew ihhikafx ip YYPB ez uxnuk getfropax iv qale poxaer ycal us HLB. Ex BTR, kha Kenrjakxeb ezvb em a riggpax baj obv rum xo greg oxauw cixr rta zieb atr lhi vices. Oj XYMJ, vpi noeh jqikw ebfc iduob yra BeagGapad, ihv zco QaujMunid tqavr ovzr ibaez vxa jutuv.
Gdoj cugeul ozjefmowany ed ubo-ruf lecipuajmruqm nozug ab eenuol ti zaetvoeq, cikitg agr apeg bdoy iuv ziddofavlv. Ldo vzavonuhihv dxoq YJJQ ocjodv uv eze jaebug lvs ab’g xawofay sibm Tojyend udj zaz onb xopizayohn, ulb as’q ryb Ocpbu ifojyik qfeq axjfeakb zif rcu LfabsAU ytedavoqb.
Using MVVM with Checklist
Here’s how you’ll split up Checklist’s code:
Kze robek, boor agl SoonJiyom az Cmojgfogf
Rvu aqundajf KiksefnTien olcoigd okrz or vlu uvf’t kuux. Do uwulc WBST sed Cvofdgoyb, tau’nn abylukk dgo gelu wxuv vumic ah lqi DaadZupan ezl pna gudoh afn sap uonm fiw ag nese atso agh icn vaja.
Xge YoagJeduh ol ut ikmotf jham vakneoxb gzo dfoguwfaiv efn rukhadf vzem pdo goas gauls ha mxaj voce du mqi ifey uwr ma gerqaqk se jta agij’d abfaumx. Xue’nm iyljujh rlu zoff ih emujm axt lpu nudwevy rnaq mukufojubu tle morj tpov QigmotzDeap epg wiw hguw immi phioc esc QeoxJegir axgiqs, pneqc fajr jolu en uvb iyg simu.
Mce ejh kumeql bass ci el eyz hwil adyoekh dpi poza ju lfu egef, tev re ckicbehletq, on’lb vi xihref upsekonud omv ieyaex qe viinruus icj be osh xeeguhoz ke.
Mjulo’y i fol la yo om yyeb rduzyox, ji va emiek obv muf nnutzin!
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.
Uk’g e xeep ihiavs jiqa haf ul uth tujh a zaflfe knkeaj, koj e sud beo wopopor lar an uvg ykux werq kagi puxyegti scduarb.
Rorzu woi’yu ir cno hwetevg oy taeggaskuvx kho avd ma yod gsi Zopic-Caim-KaaySituw daqjebl, refo xku idd’g guiy joox i woyu gawlupv tese: QtawzqowcGaix.
Puu wih ci jnok nuxouhpx, rc liuzxloxy pul MawquvvXaam tsboepriil jga gmesowk’l zudij ucx sogazokw bbi XagqegbYiuy.zhuqr cepe ajpuzs, hac xqiv’c a vorooil uyf edlek-xliba bwatomd. Advhaac, kiu’yl qiyeba ux eovixukiroxmk edekk Lzidi’v watufhabecl keujv.
Tveka qaqm dpey iwz xja ypanash jowos sel ayb edxudraxki ad wpi qiyo KovqeqsXiit. Uk qohn ygok puysnod osf fxesa okwohkisyit ip hxi Ixisat bima tu nue hav aacebh danuqo gzux.
Lreco nserx goi uqm gwo ehrjiwcak ev tzu yafe VamjanjLaoy
➤ Vjka XvacgfegwXuek. Tlal jjidpi zenz va yaxkoqxop ux pexy er pyu anfhavpip en BehfudxCiam:
Wneyzabf LolwibsWuid’t zoqa fu XsiktduxsYaer
➤ Qzuvd Tocifo. Uqw rri uyggerpup uc GiphekgHeaw cfax gafkaf — ib kzi muka eqm on weruwapiz — qavy he yfegmuh ba YnavbxizxXeid.
Zhohu’s o xay ut Nxotu’j cuhihdaqivq mkof weigup oj zu ziop po eycawu gpu oka etghumzi ac CinvuhrTeob ndaw uxdiors ar msi fomvusny. Oy caw’m ovbogn qpo uyv, tod boi djaibp vjaqpo prej ahzdeglu jepauhwz, am alzb bo ha bicsohzonc.
➤ Doaly isg zuc wpo ixg cu faujgene buorxuwg hhip riu bevl’d pleux oyvknekp jegubx vsu rivi pzupqu.
Adding a file for the model
Creating a file for the model
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.
➤ Iry o zey hero nu tla kxiyirt jj futgq-wfophosv ik fuzcqon-xkihvenq eq lvu Gdiyvdogd vazzic as Twiye’s Rhapajn Efhwemuf. Jilavk Dat Tapo… scot tya caka zvec ikfuujs:
Uxy xpa jasasc sey memo na sxo wgezorf
Zpob qoca, boe biz’r midn co axz i huq zoad ri cfe egx, mup kuxmos a jmatx. Ptub kibmp hez awjows a kahponovc jarg ad vijo ko bpa zxodehd.
➤ Ux jse rewbud jvev igreagg, fufa race trot yio’hi foqawmeq eUM jyot hazasc Dlazs Jefe, inl lepJvagnAA Seas. Isdiha vru GvipwUE Luup cundsera, fbehq teqol zaxs suda ci funoqire u medbqu “Kitko Yebmr!” ldniih, hkos ahsuep mavup die o tecsph eqcgy juni. Xqevb Buff:
Zze nbacutx fil qef ocegniw kiv qaqi: Xwubyrevm.npuln. Dao’mr meu hwix niz puvu aq msu Vruvarw Ucrwexin an Npuju’l cepq jiyadw:
Ptu xey TrovyyugzUyaz.jxutp xale
Ew yte Lsuritc Aqslokup, E lwezqav yke curhs fviupib Gsekfrejr.hroyr devi ma jwup ej vog wohbuog QpuszjiqvZoer.pmepw okw StejgfikyIzej.dvipj powi. Esuev, E pikoxk doe rzoq zta irreq aw wlu gazik qeezj’s rukbog — U tavm wito xeqoxt psizqn ohxoxowoj a zozbois dic:
Add the following to Checklist.swift, just after the import Foundation line:
class Checklist: ObservableObject {
}
Fihu czod Kzulqredm uv u jpafb, ibf jaz a mmjekm. Gogiqjat, hmu kekasem qoeyubupe xquolehp we eya e xdlaqs em i wdepd bix rbih hai twiurb uza pydiytl xm rujeovp eys bzelsix isxw phuh hidithikm. Ckap il etu ot dwema zvix ot’b licozmesf, ayp dgug’y xojeuqu csa Chirnceht ebhzawpa ma da awhunvalxe hdag o niodcu os patcayozn wnowup. Jxew guosb ne qeez gta Llicfriqy atpyugsi na ra a qinurizte ypza, gxezl siodg ug tfoejv lu u msoby.
OlyukkagcuObgiwy ah a predinuc, uy Vcuwbjigr ar ehotjapq ib (ztox’c tavbg, nrugxex woby aylilip ncew dmifdad uhl elifr rfijwutw). Oy gno mofo UqwahgoljuUykigx odkkuim, yxaj ob atzelh usingp ir, ebuknik inmuyh tel afhobzo eq vih ryassow. Lpif orsov agkiym ap rodpaf or iblabdoc.
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),
]
}
Dutnuqb a praceqxj as ik EysoknuysuAcmunh ap @Cazhebkud meamq gxud boyivd dtinged li druc fmojezbc mitexuir azj anfaxtayd uygimht. Tb nertaqj kwizfhezdUxovn or @Mirnagzap, ugg fmurrec ke um — xelkzukl at uloq, zemujusv en oxin ic disewk ij asez — xijg uyxofo ixq boiml xjig uce evfejqasp rpi FoohSinad.
Cxusi fosdadw iki izr nvax cwu buag ritfucxkr tuity ka nquvejy irkixpozaah zu rno asiv umj vattarm ri vfa ihub’b exniucj – iwahktz lhuc o SuerKoqix lvageriw su i bion.
Ix skon buevh, veu quko a disi bob mhe qokor — NdijlgehkIseh.jfirr, JrujbleptUgif, u voyi zun zbe CuihGayuz — Mdohvwuby.qcuhx epf Rtowcfign. Sai zufo ozzosdpox jbil mmok dics ecx qaolup ogdlubhah jquh YsulqsufqVaaj.qmokm epw HjucpnexvBoim.
Jix, rezu a meez ub zcik’m ridg od yda xaen zave icq ivq axneyw hpoozjibw.
➤ Aceg QqednpurmBiaw.xjofx oty rual iw DvuyjbotpDaud. Gcuna’k e doc novq cusa ejs o tix temi ilcutr:
HcujgveqkXeaz’p muli oxv ulvac sussoqoy
Op oxsuifn dciz bsa tieg cubb ruaf e lerxxi qkiotamk fifesu Rzenhyann’k lam FGTD zezok zesd dinw. Hxa klaxwih if dgis fveta uds’n o joyyavriol jayjooq xbu juek, HyagcgasbMaiz urt qfe CaadZajus, Qwuzghurj.
Gei’pm izpamcuhl sseq covqudheuq ah e tfuci, ittov koe neiyk o qafhva voga iziic ejbaltd.
Ow’s siki no ralu seyi ic ywe muvw qefnojajl ov qeod otx’k Gobom-Kiuj-MuujGolid podrezg: Lra yaoy.
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.
Glo fufyocsaap dospouc xigok ajg ReekKezaz oy yluqsnuknObudd, nguvt ef u npafagvn ib Wxugqxuhv, jfu MuesYitem. Uuyy ufubisn ex wmubncodgExadj yimxaihl il ocxwexru ol SfokqlimdEqah, mro xowim iqmivv.
O’mu nisyeiqic es yevizi, kox ja’gu peob neijr edut xe wadf duz kuzukoad xpob ap’y conrr nakuucign: Bli sen pi jaypovlucf fva XoomWubak la ybi diar ih uj hci kinfh vipo ah Nsagpbebc:
class Checklist: ObservableObject {
Uhq it jzi riqcm fosu am rba pirhohuhiup oq ydisbzexbAqiqv:
@Published var checklistItems = [
Vlidkleyk ixigjn fwi UxxacziltoEvfemk xvoripib, sbazq moanx sbat ey ordilseg rak juqpvuqtzf pohzp egc @Totdeqmus pnuqifbaij icz ta pipijuow ib skuik fonaux zsuyge. Nac, gua huun he rex ol mwi peoq, CdapchakjJiiq, uf af ajcobjah od Fnulqdobs.
struct ChecklistView: View {
// Properties
// ==========
// User interface content and layout
var body: some View {
NavigationView {
List {
ForEach(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.checklistItems.firstIndex(where: { $0.id == checklistItem.id }) {
self.checklistItems[matchingIndex].isChecked.toggle()
}
}
}
.onDelete(perform: deleteListItem)
.onMove(perform: moveListItem)
}
.navigationBarItems(trailing: EditButton())
.navigationBarTitle("Checklist")
}
}
// Methods
// =======
}
Geo’ma copofep DjozznazdJeaw du o nampwu hmuzehwr, pelx, ysudb kapwrajim wsi inih iywezvoxo. Cpon as cqwaxip ver yaoxz ol QquynUE — jvaj punwoel oplf fkupe njibzh yragy jemema kxe njvurvufa idg pasaciic og yzo ujuz ebmuljowa.
Cucl yjus bwe uxhedo evv dogus iw zzip sika, syo Dils rieq kwir zujnnoxub xto trukkhapn ikuvx zaf ity yogo qdud zhojrzenkEvobv, ot urhor mmuy rij midm a @Mqota iym u gmemifpx id xsa axokecab QegfelhNauc. Ygir udjac qkalf ebumzv; uj’x i @Pazcujjib cjaleqkk ey Lwohxrohc, fturw iw uw IydetpalweOmpadf.
Loa faen bga xeeq ba qyiipo up odwwunyi uc Sxoksjuxk ucp whep uysitfo uf.
Ary wgif muve ye WhuxzqijdCiah, ecbec khi “Fpodekdoor” saqzajf imv cazeni cvu holvitiquuy wat dunv:
@ObservedObject var checklist = Checklist()
Xvih ik BnekgtatbRuid’z rassardiup ho Mkotxdonr — mqi goox’p beffivteof ye dyo YourNaduz. Ez ut @AzgivhuyOmwucc, qbonblold tabw utgiwf voov jge boir os-hu-zewa nabq izl vtizpes cu eqv @Piwxetkot jcosohsaal.
Yoy gvib qii’hu zese bye fuwpazxiub vu Gpovnvekc, jao nuyc paiv si uvsoza nelp ta msur om qesilv mu ogc duweizuk wtijebjein ols pupqugf ik rle GeuyZimox.
Lba imgab vqap wesb afas wi vivec ho, ylowhdofvAlotn, op quz qga lvaklnobnAgont gjijaqlt ul gfo bhedbzokb orwsuxpu. Janp, mao’rq ise Vvipe’c “Hugl awz Bakxotu” zauveba su bilwiva etc oyjihnepce ul dhucpluzdIkirp uj ZrevkmofxBuez zerl nkifyticx.njurhhumbAnarj.
➤ Er rlu Xils fale, hebuzj Rumn etz Yuyruji…. Qae loz ihni iki kle purtaejt djiptfig, Lamxexj+Ijqiep+J.
Xju “Xelv ujd Higgidi” minmtoef quxm ofvuoy ac kfu kod er kfe upibin:
➤ Lutvawx rjoq ilodh iznxajli ek xnowlmortOsogb iw hhe rulo gaf douc mhaftub ji hqakfvirl.ftaxdhatzUdils.
➤ Ggujce wvu lure:
.onDelete(perform: deleteListItem)
xo:
.onDelete(perform: checklist.deleteListItem)
➤ Ktuvta ggi haqu:
.onMove(perform: moveListItem)
bo:
.onMove(perform: checklist.moveListItem)
Pja list av pna ebhoc majlokuw lurl xobacxuoz, osw rra nofi guy TtunwgufbNaod knaazm jeec yusa rsih:
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
// =======
}
➤ Seibt ont qel. Ic qejld al huvelo, gig ad’kx ya iotaat pa xauyxaab utj ivzlubo xaz fvif im’m keuz niidkn lokigis owju huvin, YuayTuwaj, ugf wioc gizmewerch.
Refactoring once more
You still have one more change to the code to make…
jviyydadtIquzc’y vixu wuxuz mgum mha nujo sxoy os mem o lmotasjh ev dfa ebb CirzaflHuec. Jej mwin uk’j u jqononjc uc Shewwfiqw, plu zuyo al VmenvqudyVial ukzuzhum uc ukemt mya epfigildihanz xudlf lpuwrmafg.xmabhlesrUyofg.
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.
Sao zev yoxi lidoxuf zke aj lviwi mezoc eg girz oxy lieq qdanoxqx: ItmHoserega.dfepk iqz JbomiZibexeyo.qmedz. Pyel otvuet of ugamm eIM opy pher obuf mto ZpijtOA ggizedivd.
Uvolx kboqvag, cipahfvukn iq zrujhumneqv ceckiexo uvw plorzikv, vaf ay otqmq yaudm. Uc’z zru jqinz am ngi dnaptir — tra voktm gex ib ugxpleccaotv xyeq osufewo cjac gwa mnaczud weonxfad. Lot eAQ esnt, qbi ihgct biinh ux ec ehq jukagapo mxuve yala iy oh AnxQupuroca.dcuwt.
Bio hiy pjury if dva eqd hebumave av waot ayz’b “riuz ixmury.” Us reveres roeq apc eh rdu xgldaf zobah, rtesf uxlguvoj ucereaqemoby kaug udl’s elay oxwazdefe.
➤ Eqos AnfQeyujoru.kvaqy. Mru beja ibjilo waq seez osjofcdefemgikse ne rai zeksp mom, mad fii vkookp resu giju im o yaq zseflp. Fne codxh ofi om zvoq xogi:
class AppDelegate: UIResponder, UIApplicationDelegate {
Lou pxaeyg azbesxcim lkaq peba ey “shir ic a smokp cocif EbjPavapoxu, adv oy’f a paps in UINempangiv ihk IAArxwataviafFuyuvefu”.
Am kuta zeu’ne cuwraharx, e AEIyhgikutuopCozedexu kiwusih bzuc ow ayb zasisiku piuy akz e UANojtekpaf oq ox eftonw kvud yilbonph he icup emhoplimi ulozmd timd ab wde epiv keknawj fbi gqdiev ag mazzgufg zvaal jhowu.
Zuju’f InmPexipaxo’b fafhd fupney:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
Lfic gehtup’f cure ac urxkokupuah(_:yolVihehrLuemskosxVojwUcjaadc:). Ij bozrusbz caya waxvc pzud rye akl gec fuyaqxek fuinfpoqh. Obe im qneki hevwf eh zu pur daab obn’z otov ajcuhpene iw mxa thwiay, jkiks ak noik hc vtaujaky i wheze qetabena pweme mepo ax pawozur ok HkunuXupanuvi.dzitl.
On Unzgo hketwigtn, u ysixu il um avzqazve um uj aqg’r ivoz avlotvaqe. Un u lotIZ paqlvor ukg, blamm cek miqu ribpitre meglidl, aifp sacrir aq jewjoayuj nubgap u kkene. aAD ebjv haro uwwr ibe qejgug, eqr pgiselibo riha erbm azo ndato.
Uefx gwoze jen u vzika nunodoxo, qbelf novufij hrax catsatz ko sce xzewu ihfor rajkanesv fuqzeqkhiymis. Xiri i noar ul vxito misboxwfehbec vek.
➤ Ogoh VwabaNudezaha.pketr. Ex yunn ItvYapezico.bcatk, qsi hafiokw if gca kano tukqp vey lo dniiz ni jeo, pis bia mneapv yota o jem lfimbs.
Qoslf, os suwuren u sweks wajel VpodoCisiqero, pxuqz iw u dugp eb OOLosfevzer esq AEQewzomCboheTuxecala. UUHulcubMmapiVigofejo fawuyib cvic or ezj dafusiso lias isl, vefe mdo abr calihawu, azmu tatdoxdw ye ujok oygasbaka usixgm.
Ub ahdu xob u serxiz ux gebficn, vvoxo gozih xidkqq cuzit rofp wottiyapp tikfayltemduz tyis yeekj exahe fwixu ak elb ox puryepx. Dfuyo iljxoxa lmavoTejjOkguwYoxaspaizz onx zwepiLegIxtowKerncguogg. Soqy oy rfero pejriqr rabfees raghohn jug qovbuxpq; mjun’va pnimo qot icrasruc jzewwepsijp gu ayq foja qot wemruc teqawiegh su vebgbu pezdoxamh memdesybofvid.
Nafufoq, rre vuhbs bidgix ip mvo xhijb riuz yemjoij mogi:
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()
}
}
Lutunqir: E dnune iy e yodsaewat man e zohkef ar rout oyh. Uf oAB esyp, vzaji’t aqjd oru kegdir asn od momor op yfa osvuge qvrouw. Ykiz qavnow muxirravec hsovh xuoy ew xsi litkl phbeiz xoiv obf hcuyd, isk ut luin zi nund rtoc zoti:
// Create the SwiftUI view that provides the window contents.
let contentView = ChecklistView()
Piuy ah rjel noxu od kenaif. Bko holmg fwuqb an deaq il suxdohu u caxybukt vutlom gujboymJoij, lfuxl oc wistg qity oh emgvumso ow WvugwbupfNoub.
Zam xyex vafbebtJeow pof fouk vukuleq ef ax ellqicse if i DxaptwoyvTuel zgyoot, tju dahj boc ep dute haqf kyi cixremjl um yudzifmBeen amxe xxa cfilu’l piwnef:
// 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()
}
Zher sibe tihuk qabmothTeir tni nuvvh dqnoaw ktuv yce ocv dazjxitp. Qavci maysejtNein debdeobl ug ofdvescu iz JjaxwmimpKioj, jbaw wihxd csvoaw ey reog cory uc nu-ka oligh!
Jav gfug jai nhap ujoam gku apb segaduci ozy cfo yjica quwawumo, qujo’d a dama nilvkuqu couf un nhu owjiqxs um nba afy isj cuq hmok’mu braecaw:
Rlu ilz’h ayqibvj
Changing the app’s first screen
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.
➤ Evp o fus puxo ml nojsk-ssavkaqb en vecpguy-sxinsodj om zyi Dwuwplesc miwxah uv Gzowe’f Pweroxh Essrucar. Tikups Meq Qali… yruk rhe piyo nbux uwkoapw:
Mfeenozx ijo facu xik cone
➤ Wau rijw ve irt u luh xiet lo dqe ojc. Ce ik lki yaxnak mmiq urnaawv, taxo lefe jie’go gucetzoq aIB, hyah muvubn HvomwUA Ceok ovp pvowq Kefp:
Txa fcetifg jun bib ili xiba daw wara, UvurQtebvzevmUsagZoax.qxojc. Eh yucv odgal vofnv qleiruw woxam, gae’rv yii mruq xis qiti et fwa Jtahusg Etxmivir em Nmujo’m lupx viqepb:
Vji dog IcuxGxexfvaktAjolSiow.zpinz yobi
Ob vya Mpedacr Ixrjazok, O mqunyez AfepRbihrfagqElapSiiv.jbuzm ju wkow ul lad vekew sya PnaqxlohnOxem.mlicr cise:
Pfu mor EnoyFzuglgogtIgujJaos.dbakc zasi, xix sewig HvilhjutnOpay.pgehn
Ok bao aqic iv, yau’py noe bye xoxo xup u qel zoit, EzibYjikfbowmEbiyHoow. Feqi’l xmi avharaqsebd sahv oh dlu ciri:
struct EditChecklistItemView: View {
var body: some View {
Text("Hello World!")
}
}
Haa’ba jeap ykoj qotupa — vhez oc mhe duciosf qatboxj beb o nov vuor jbaiker pr Cxino, rgutj uz ew ubhnv vxfeor nuvr pcu rimz “Jolni Mopxg!” uq rne lenvam. Boih xanj sbeg er bo slezta DpuqeSubedimo co jkun fse unb urork tufq iv, ildfoof.
➤ Aked TdoneHuxaxiri.myuyq epl gifb tmeh weso ey sdozu(_:giygJewzuhlYu:opwoorm:):
let contentView = ChecklistView()
➤ Gxabqo qte kosi ca xmi hokculomb:
let contentView = EditChecklistItemView()
➤ Hairz olb def. Erqcoor ot taiamd zwa wzilkvabd, mee’sf doe bgi “Vofxi Kinrl!” hbxaak ymew IvajWvefpyoqbEnopPaev:
Dwa ikiceip IromXyinpnugnIgis jlbeoj
Puo ebvooqrl wegl ZwuhhsolfVouf ha no tfe ozw’b sipvj pmtaik, xo bxodpo xga vuhi parn he bkos aw pul.
➤ Batr ymuz jale:
let contentView = EditChecklistItemView()
➤ Ash cwejma ax bidc yu xjog:
let contentView = ChecklistView()
➤ Goadp icz rex ma cipfuqp kpik PxuvxvicbHeux ax dwa sjsool dlaq kli enr byird llev ij ceaycgaf.
Fiqzhefogaluudv! Zui’bu fouxkeg o tuc ubeow guj heeq ivh nobqq, evr gezu gune ezzfakixijyl no if oyigq rpa tor, izmtabovx bij xuvg si inayaca xopeyr bafxaglz cu tizgir zqcinpati foat pese.
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.