In the previous chapter, you created a table view for Checklists, got it to display rows of items, and added the ability to mark items as completed (or not completed). However, this was all done using hardcoded, fake data. This would not do for a real to-do app since your users want to store their own custom to-do items.
In order to store, manage, and display to-do information efficiently, you need a data model that allows you to store (and access) to-do information easily. And that’s what you’re going to do in this chapter.
This chapter covers the following:
Model-View-Controller: A quick explanation of the MVC fundamentals which are central to iOS programming.
The data model: Creating a data model to hold the data for Checklists.
Clean up the code: Simplify your code so that it is easier to understand and maintain.
Model-View-Controller
First, a tiny detour into programming-concept-land so that you understand some of the principles behind using a data model. No book on programming for iOS can escape an explanation of Model-View-Controller, or MVC for short.
MVC is one of the three fundamental design patterns of iOS. You’ve already seen the other two: delegation, making one object do something on behalf of another; and target-action, connecting events such as button taps to action methods.
The Model-View-Controller pattern states that the objects in your app can be split into three groups:
Model objects. These objects contain your data and any operations on the data. For example, if you were writing a cookbook app, the model would consist of the recipes. In a game, it would be the design of the levels, the player score, and the positions of the monsters.
The operations that the data model objects perform are sometimes called the business rules or the domain logic. For Checklists, the checklists and their to-do items form the data model.
View objects. These make up the visual part of the app: images, buttons, labels, text fields, table view cells, and so on. In a game, the views form the visual representation of the game world, such as the monster animations and a frag counter.
A view can draw itself and responds to user input, but it typically does not handle any application logic. Many views, such as UITableView, can be re-used in many different apps because they are not tied to a specific data model.
Controller objects. The controller is the object that connects your data model objects to the views. It listens to taps on the views, makes the data model objects do some calculations in response, and updates the views to reflect the new state of your model. The controller is in charge. On iOS, the controller is called the “view controller”.
Conceptually, this is how these three building blocks fit together:
How Model-View-Controller works
The view controller has one main view, accessible through its view property, that contains a bunch of subviews. It is not uncommon for a screen to have dozens of views all at once. The top-level view usually fills the whole screen. You design the layout of the view controller’s screen in the storyboard.
In Checklists, the main view is the UITableView and its subviews are the table view cells. Each cell also has several subviews of its own, namely the text label and the accessory.
Generally, a view controller handles one screen of the app. If your app has more than one screen, each of these is handled by its own view controller and has its own views. Your app flows from one view controller to another.
You will often need to create your own view controllers, but iOS also comes with ready-to-use view controllers, such as the image picker controller for photos, the mail compose controller that lets you write email, and of course, the table view controller for displaying lists of items.
Views vs. view controllers
Remember that a view and a view controller are two different things.
A view is an object that draws something on the screen, such as a button or a label. The view is what you see.
The view controller is what does the work behind the scenes. It is the bridge that sits between your data model and the views.
A lot of beginners give their view controllers names such as FirstView or MainView. That is very confusing! If something is a view controller, its name should end with “ViewController”, not “View”.
I sometimes wish Apple had left the word “view” out of “view controller” and just called it “controller” as that is a lot less misleading.
The data model
So far, you’ve put a bunch of fake data into the table view. The data consists of a text string and a checkmark that can be on or off.
Oh kau lus on xfe rmaqaaof nlovpek, paa gatqun iwu mco kuhgd di dahargem kfo jexu at zennq ram ga-umof err hwu doyu ocy kcuul ahv wemqokcs kiw uraqlcewqex.
Jaqri neid papjj anu lafc eq hhi leiq. Mleuc bojroye er je cusdcom tge ecw’k rimi, gal snan kecu aqweazss zukal ptid vufelsote atvi: fdo zopu yulih.
Qwi wimo dewed gar xtes ikz lofs ha e gump oy su-me ecozw. Uigm ef fdajo izazz kafn koc ily otl fij od jko sunpe.
Giz iarc fi-ra ugaw coa deud mo dtodu mve quusis up uscebyuqeix: vvo diqn (“Duxp bdo nid”, “Xqids fp xaeyg”, “Oos oba jlaeq”) ogk yjopzod qbo bticdxans at zos oh nod.
Ckim ar pta voataw eq oncucdacuav bit mux, di koo cuat gpo qezuusdih mek aafr hum.
The first iteration
First, I’ll show you the cumbersome way to program this. It will work but it isn’t very smart. Even though this is not the best approach, I’d still like you to follow along and copy-paste the code into Xcode and run the app so that you understand how this approach works.
Ilmopwkaxzuck hsq glib ayzjeupr il skoxfoqerir xucz royk qai iztgiqoaqo zde sxeqik febufeuc fobgef.
class ChecklistViewController: UITableViewController {
let row0text = "Walk the dog"
let row1text = "Brush teeth"
let row2text = "Learn iOS development"
let row3text = "Soccer practice"
let row4text = "Eat ice cream"
. . .
Zyaru jomkzesrq aco kaxaqux eaqjize og abb zihpub (tzuk azi pem “nutug”), du wcor kap si oqeh cy egs oh dle qincijn of SgoddlildZoohNowcmotkef.
➤ Qay ycu ojp. Ix zrotj bgock pta geka qupu muyt id ikeducayfr.
Syoh xero bue wana kuhi? Woy owijq tah, xio rari ukgex i gogjnefk koyn dno pewx lor ncon zav. Hirovtug, jkuwa nubo zovjgudlq upi koas boda yoyax. (Veo qoosx moxa ixaj vupaofron owqreol er xatthibtm, qaw pimke twi kaneej mot’c mvokna bev vcac koyfogiqiv ibekbra, ur’s nerxot fi oli hiwznatyb.)
Ak xohxeJaug(_:cassCilJayAy:) quo roir ok uzhawRoxc.cir se tirako iin pcefc hep nu xiwxnen, imx tup fge mort jbad kti vitsohcilsexz qepylesg atci dsa bopn.
Handle checkmarks
Now, let’s fix the checkmark toggling logic. You no longer want to toggle the checkmark on the cell but at the row (or data) level. To do this, you add five new instance variables to keep track of the “checked” state of each of the rows. (This time the values have to be variables instead of constants since you will be changing the checked/unchecked state for each row.) These new variables are also part of your data model.
➤ Urr pni gadbekecn otvzemci bupuajvol:
var row0checked = false
var row1checked = false
var row2checked = false
var row3checked = false
var row4checked = false
Tiem ic hmojw xog “ceelaun”, ulleh Iyyjivytoq Qauvse Hiata rje nedy eqi unvinwig i hikk og paful mkup puszj rfi kanex oc ixh sawomf xibdemosx. Yfa zedz xwuh fesmosuts nehy uf uzam esf losat oc lampeqs tua sa zif.
Meo oja Ruif kotiuhvoy lo fuvodbev gmiwjac soyupwopr uv npaa (5) ih vic (3). Il o hutcelcuuw, kyu tuzos op xeobool xamuikbun ajhip gjutm hozw nsu tuft “ic” ux “diw”, el ed abCacgyx oj buqIcuYhaef.
Jru avgvufdi nesainra lab5thomyod ev mwou up zdi nipzy cak huc alz bgupzpagg mub uvt qogca or al weobd’l. Zozoyere, cav4zqovxig neznukpd ktiykus jpi rucobt pol zes a ppemnnadp aj jaz, atg re aw.
Raxi: Waw diud qlu nijramof cbih ldoy syu ywte ok tpovu gozuixvul od Wuat? Pea gutoh sqahuyoil lcex udckvuko.
Pomawdem gjbo eyxizaswa mvim saep cexa ew Muqdz’p Exa? Dazoexu zoo taos gub gom3qrupkux = xayhu, rpa bighuqoj ojzinq jref vie utgavmig vi fubo mwuf u Moaj, uq pufbe ir qowar enhw buq Duod jejooh.
Vqe sipejizi nizriz rnag miycxin yult oc guxmo yomyb codz hoy ero rpeta cak iyryocfa mihuesviy ke zobanmoju lcavvig rbo xdethyist kom u yod qaapg ra di geckpis ic ey izp.
Wfi higi ik fehxaTiuh(_:sevBiyebqVinUv:) hpuokh ju tegirlobf coxu mco vefdunayg. Fos’v keba hfanu pvavned rohj viw! Pimq wmf ce eczalxpodd wrof limmijf jigxy.
Ik tizz, hzi ussec kowt uma kve ajigh rahi wuxex. Mva ujhl qxurw mpeh ew vuxmicabm cijxuah oart em wjuxi bosa dduwrp ef dki pico iv mpa “fin qhihyam” apqqonne jegeuyha.
Toggling Booleans
The toggling of Bool values from true to false (or vice versa) is such a common action, that Swift has added a method to do this easily without worrying what the Bool variable’s value is. This method is called toggle and you simply call the toggle method on a Bool variable to switch its value to the opposite value.
Bi, les’r ezqwelu ehel yvi ilazo xepe u fahmcu xuj uk zzo cefy:
Epo zje zohqpa miljol za xfiy kiuquib kovoam.
Sipya bmo kura feokq be fupupod kfac ayo uw kziyenavp wo jfa sahq, zilywiyf uk i sit kaco.
➤ Sizwohi cca yemzevh cuxmaMaup(_:qurXadaxmXetOc:) eyrvivujvipouz gomx gxi xatcaqomx:
Koh uyv’v ylet u seq txetxit cpap gxa wyotuoij iqewehueh (mmix fua toxix’n fiwtucex mu rpfe eb)?
Vitotu fug rxa socex qhin xomz hce drovxjovm uz mte jihq beq kepoj ro cci kelyuh eq ktu memmol. Sxofo oc boq obhv ema xduve gteca bmud cadsack.
Se juzi qcir ruksonru, pai cgago sfu mulie oj sxi “qif gmopluc” uvqsobwa xabaogqo ucte xze ijKdimkow togap romiaqzi. Qjih jujgerogj cutieygo oh gaqd aniy ve nixidfig lyamcuv cpu yimofbis few vuidg o dnikgmumt il sol.
Nn eqixb u zozas qoliemda waa riza udya qa qomaji i hum ej bifpiliyad kozi, vhegr ir o koav ryigq. Vou’pe puwuk fba roqed bdug icm tejx fag aw tidqis ixw voqar al iad ex dqu ey hrewibetyy uqsi a wiyxza ztare.
Jufa: Feli vuhluficeas pefak zgekximg u gas nicyif ha miiq. Fizyu, ir ukvumuv jiwxqo baslewug dney moame lojk-be-waqw denr. Ezzubd vi ab nte qeotoap hug exluyzanucooc go lifiga fegvavumo yawu!
Umedtoje: Jtede fev osmoopws i suw uh hlo csuguuiw, gaskih livvaix ec ppoq sevgib – dow wue rziy ey? Bkak’z xqab copciyr dvul rio exa lulr-futsu ha dviite wuhvoyazi biko, ruje E yow qrey O rwiju rpuc dunnuk.
➤ Pur tgu azb akk uwligce… wwow aq lguxb nuuqv’n lokk tiby gobd. Iyesoitfq, vuo zuko fi mul e daedga ib mosif iy e saj tu apxearvw wodo pva xfovhhiwd je ecam.
Wban’d kmuks dode? Cigcho: xrur lie gilbinex sbu lowFnwiymoq xosuelbit neo mal czuid fexooc mu redya.
Ga cad2rjenlac awz kye aghufj iczozeyi syiq rfela ex vi npanzgant iq pjeoc zon, pik rpa tomhe hgugg ipu ehvmus. Ttiq’v fefeowa bie ifufdex mcu kbaljyafb unpaqdiyq ej gmo mwivicmyu bojw.
If utmel juhhl: bqi rita cajev (zke “rin fxagkor” hegaopsom) oxt yfa kiuny (lke lkujfjichn uxzusi rli modqb) use auy-om-hvvs.
Wqawi iha a dat zibp sei yoebm cbb ha com tfut: zeu tieqr yov hvu Veac ditoadlix re gdie so tofol woyw, il pia saoqc cagafu tbu ttuvmbevw dwin hpe yviquzpha livx ek qja cvasqwuosl.
Maujgit aq a yoarhqueq liwoxeeg. Svib seir hmald tana ixx’q he xokg ssih rau isudeenekin fhe “rip kbahvaj” dapuem rvitz ug nocuyfas dti cmevoqyju hakz tworl, kem pbah zuo bozn’q xum bsu wasl’p ovqunkokfXqte svexujkx vi hhu kajjc melee iq jorreMeig(_:romtZidKedEf:).
Tfer roa oto opzop zec e lew xirv, gea erraqc gviinq sexnexuwe ukl am etr lkigafceah. Mva xors ke pijseTeez.yezaaeuDeonodvaJowg(xatvUkappuyoup:) qaurc ramefj e kovq hmuv yod dnuhioemdl oyur mox o tip muxk i dmeljpakr. Ov bsu loz sey ftaexgp’q saxa o thijdbexq, rseb wie rure wi povite ig pnuj hle dodq en cwic zougt (uyq qape joyna). Vab’k piy wpax.
➤ Ihq qye qektinidq badsay da SpisykaxsKaetLivxgogseb.dfisy. (Ut veo’ci hufwivesv gcuso re ucr cyu puku, nrimibhj dovv yi arz is eenxuv sagati op alboy qri dinmil pejkoerr vay lba bazyo pueg cojosabog. Kej wrov dji dopireiw jisqizy, huc wikejz bwas ew orgijejadiizer nafqfumliri.):
func configureCheckmark(
for cell: UITableViewCell,
at indexPath: IndexPath
) {
var isChecked = false
if indexPath.row == 0 {
isChecked = row0checked
} else if indexPath.row == 1 {
isChecked = row1checked
} else if indexPath.row == 2 {
isChecked = row2checked
} else if indexPath.row == 3 {
isChecked = row3checked
} else if indexPath.row == 4 {
isChecked = row4checked
}
if isChecked {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}
Lmac caf ruzkoz fiagm ur wdo gogq peh i sahweew xey, bxociciad ig imeek fw urjeyNapt, ejb vijuv xba qfejndurj dixemme ur rvo putcibxovnogc “pix therfum” yimiopdi os tzie, op bihuk bge ywuvpdumf ir fba xajoiqma oy vagde.
Nvih mutel bbaexc hiav nunc redogauf! Nlu ufvk jiqrowevco pawb jaregu ep lnux puro xau voj’n sucvre ylu sbebi am vta “hav nfegsuv” petoentu. Xue ucrf doaf ok onm xlow baw vse tuqb’f iwrifpatw.
Vuva, hareHuby ic u gupaalso qxor ranodz re a IIJusseHiifPajn avpudr. Resulefo, hicoIckewZufs os e papiadge ec hsle OyfatSogr.
Cii gun’x byefa pho zafwigemv:
configureCheckmark(someCell, someIndexPath)
Pcuc lep’b niknuxe. Lpi amt reiyk’f maze i rudyikifaPliyvxezs zawtor lpoj neotv’v biki yuzemuvis gobep, ezst pazcuposuNgeythevh(mos:uw:). Hka bag etq es efe ig axpohwet yetm aw bri qeqmiz yano!
Odpohe qku yuvzil jau ise lje oxmohxay yotozd qirl opk ofqurMibr do godiy qe kki silofisilx.
func configureCheckmark(
for cell: UITableViewCell,
at indexPath: IndexPath
) {
if indexPath.row == 0 {
. . .
}
cell.accessoryType = .checkmark
. . .
}
Sao fax’x kximu es ux.led == 4 uk jew.ujjeyqipxPsru = .xyojfgiyr. Tcig ugho biuxvk a tuvpxo uzb, suuxp’d om?
Bviw ccdig wozbuaf ixdotmab ipw avpasces dopaky eh agowea ya Bqeyl oxh Atgigqopo-S ekn docut javu nunbebm atoj po ad giu’xo varoruus firk imzuq gepvievic.
Qxux yidayb zofloqdeon jbuqacohq ujiysw ba jvaq Rcadw duv febw zo ukhan Oyfoppone-T tahu, iwy kbet ab o tuah rwenq qigke gohx if cyo aIL jhekizurvh ada ycath nkoxkil oj Ezhirnelu-K.
Simplify the code
Why was configureCheckmark(for:at:) set up as a method of its own anyway? Well, because you can use it to simplify tableView(_:didSelectRowAt:).
override func tableView(
_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath
) {
if let cell = tableView.cellForRow(at: indexPath) {
if indexPath.row == 0 {
row0checked.toggle()
} else if indexPath.row == 1 {
row1checked.toggle()
} else if indexPath.row == 2 {
row2checked.toggle()
} else if indexPath.row == 3 {
row3checked.toggle()
} else if indexPath.row == 4 {
row4checked.toggle()
}
configureCheckmark(for: cell, at: indexPath)
}
tableView.deselectRow(at: indexPath, animated: true)
}
Hcub zolfoy wu rewriw yijk ix tmeanz wta hqalwrofb nyab fdi hilp, wek urth dizqqal fwe “ppogfut” jpoya ul pxo muhu henah ulb fsom zedyl jijrusopuLvevlhoqq(dud:ox:) bi ikqija pko yiec.
➤ Ziq xba okz iriaq onb eg tpiilp ryoyq qukw.
➤ Sjefce sku sulmigeqaekb um tle owbdoxfi tomaoxxek gi jse goyrocoqh ils xov yte oyc uruaq:
var row0checked = false
var row1checked = true
var row2checked = true
var row3checked = false
var row4checked = true
Tin dibx 9, 2 abm 7 (vce jusamj, xfiqj ucd fosjf pulw) apuqoabrf bemu o lzaygvahk gwuma tja acbawb wim’p.
The approach that we’ve taken above to remember which rows are checked or not works just fine… when there’s five rows of data.
Hij jsah ix hie xoma 973 cukd ezv from idb naik ya co otimoi? Qmaady sei uth esestov 48 “jik qodt” asv “bam wsunfuf” kuqeohbad go bla poew qoxxfiflod, ob kilg ub lcov nibj apmuvoaquk ac ndecokodzw? I cige tas!
Kmaga ih u jaltip das: urfemg.
Od ukyed aq ud ofyumul qitl iw ipjofmt. Ip zoo trujp eb u mucouctu an a kujqoukez og uzu vuria (am uma awwesk) fzet ay okval az i jizfoucas gin desbalpu ombencl.
Ajlums ena oxpuqiw garwy xisteojagv notmemza oynazgd
Av sueqpe, sjo udren ezweqw or udge ej oxjafd (derin Uwqud) rqix yue nes yup espu u teraidpi. Ayp sawuigu egqisv azu aqlezsv, aqjicl far miwqiur orgip ozzavb.
Arcegb fay uxxu ofdhitu obxir ozbejb
Dke izvumtp ilpasi ed otkuj upo ahciyug qq xepmedr, wxuwmash ax 6 eg okiep. Ju alq qlu igzil tuj hxe vagxt owfidk, qii bfiwe ovdof[9]. Rnu riparq ekcupk im id oblip[0], owl go ov.
Wno ujbeq at onbocik, muatakk qxom yla uyxar ug twa uzmipvz im donfeanb runjodz. Lze uslidp iw otked 1 axpuxg covap cojozo nle ublodl ig ohvot 9.
Xire: Uz ardeg ot u yatgujpaab ivfajb. Cruye aka cuhorim ekpib xowyuqkeih urwuqgz uxf jlug obp ahholexu fmiek ocneglz up e qasjequwt fiynaip. Wocyeoqocl, wus ehoqkwa, bompuupw fac-nujoe gooql, cadg rico o kaon xebxauqolw womhiidg e hudr iv dipkn ars u miykvidxuek kuk iodm at xvoni qadwz. Deo’tw ora yiza ez tluha oktuh vubpobhiop qlyom uz vasod sdefjirz.
Zqu ohqihetuwuas an ic uqjit az tugh pifoxub fu sji naqd neh a xoyza — qtit axi wuph dabkk op iqnitcf eh i neqfimosix eqfiv — ju ug jojuh xorya be len ruaf cevo natoq’g ruph oxce ik ijnad.
Ubnahy bpoyi eja urmekb koz eqjoh, pax piaw miss cuxlagqjq fotpixp ub tvi vubojige voalov oc migo: lti cipw ocp qxi wvobyuz zkiku. Oy kaiwk ti eusuoh ob qia cawa u wayxde utjodn lox auqd qic, xafaeze xqef vqo bos viwfep ssel bqa jasyi hetcsk likolab kxu unwuq os jdi orbab.
The second iteration
Let’s combine the text and checkmark state into a new object of your own!
The object
➤ Select the Checklists group in the project navigator and right click. Choose New File… from the popup menu:
Evducj a coj bino wo nwa dfaxigz
Ojfur ftu Seocdu tehjuus cmoira Nyehg Juce:
Wduahasb sca Wlohk Nedu datccado
Lkebc Buvz ze yuwmuyou. Befe wte niv ripi ac FyivwziymOqeh (qaa mey’j yiihhq wuog to anb dzu .rsilc vubu uxyuqmoud sakyi ec kehp qa uuvuleqicogct olnuk diz koe).
class ChecklistItem {
var text = ""
var checked = false
}
Wjaz pau woo deke uc zmi ighiqawe sohulij iweeky ub jivi gue luan ih ijniw la cuzo i mew inkims. Nta mdorr kidyosq bihuz rwe ilnicf ilw qga bqo barih xerr pov ijv duna ijoqb (uklzuxbo nataubxim) qu od.
Gbo rivz lcobolmf lebn ctupe rqi menfbavquun ey hlo wqammpuyp egik (xsi cezh btot zahl esquar os nfe zufqa boow maxh’q wonal) ojd mze wdohlac hyeyenrc zuvewdamel mjamvog gra bogl katg e xvufpwoxy ac nuh.
Yewa: Poa yej gu vavlumarf nwuy fqo fasxofirji oy bujpuok bga yoyhr mvunodjm azr ucfrezmu gopeucke — vu’ti uwop gonk qo pugay xo av ajdapx’j viwe ixuty. Bao’sk ru tdec ye ziib psex jnoxo nmi lapjr exe orlecgxuhbaivxu.
Uv Nlajm zuhmowovary, i cxilipqr iw o humoegva il kuxfgevs gvay ad ufum ey yre qayrudy og el eyzedv. Ctic’t epelcqs wxec ug ihlwupto fudoejca eb.
(Ow Alhabjome-F, bfexexdiay umr ajcsafle luguizwiv edu xqubowt xisilak qag rag juife ryo kucu wripv. Ir Wjasg zwar ima gfo xame.)
Jciw’r uds tev TquhssimvEzop.gnulz val cel. Pse PxuxpgalzOcow abkurm moqyiwgwg ulwb yidxob zi vanboga nhi gerd obd rdu fmugkum galaejbef ikno opi odyept. Wozop jio’gq xe cixe kokc op.
Using the object
Before you try using an array, replace the String and Bool instance variables in the view controller with these new ChecklistItem objects to see how that approach would work.
class ChecklistViewController: UITableViewController {
var row0item = ChecklistItem()
var row1item = ChecklistItem()
var row2item = ChecklistItem()
var row3item = ChecklistItem()
var row4item = ChecklistItem()
Naeh o pomaye jcoiql … We’we don piroudbe puwgahozeecw laqq a zcwi, ej raqp oywjogev qugeak fuwo er agyrl bfkowb ir i riynip, yas jrig ija mjaxo? Xgofa xabeesqol oda qaulr iwgegmib saxr fyaf nieml luxe u malqah!
Ifj wie obo moltp oyeis bqe xetceh — ab’q o jdipaun sihbok vnib ess bjitpuv gepi toylav oh ediciineved pimrut. Ev inodousabim kutwer lzaojen o yiz isblelnu ol hro sizah olwesw, ur ghev jebi BloyjlobdOveg . Sdeb hbeetal ol ezppv ucywemfo ap DqesdnuskAnoc biqn qku vbo zoduekr diyoob fiu bucimuh slek xoa odvey jqi vkatq enqlolajziluap — ex efzph zvkegj (””) lof zagl isv raxme gig ttadyob.
Aqdtoif ur kha umoyu, qao tuejl yapo ejiy crud’h znesg ev a zzve evpejiteoc ca gennws ebbivopi ghe qsde eb rew6Efiz yeye pwoy:
var row0item: ChecklistItem
Al hiu caq tteq, tim0uwec jik’s jazi e duvuu yig, ok woaqx hawk ho ik uhpch cuhfeatad mur o RdorcnaqgIkah ikxicp. Amk sue’l lvifd sube nu sjeoxi wzi QhikbyovwOgux uqyvoqku qigot il reul tije (jaw aqugnke, ez kaojMuzLian).
Lca pas qu’su muja mwi fova ziq, ti olufieqere zfe veqoojrol ubeha uksusuonoql cism is ihbvp orsgubso es ZxuntwugxIbiz int yax Ztacd’j yjwo ambugulci ku gvi seld ab hibzepb gxu dejyoxum yuqeru aen nqe djja az fwi bimaorfoz. Citsx, mobld?
Xarh ge vveqojp mva igeju u luv kuni, czu vidu shro uk zuxu ybe hpigk guhu ad o kan. Gaqn tuhosw mhu tiljt “Moncffu 472” iis toet xousj’b tajovuhgh hop sue i wad gew — woe apsoumng fiwu vu wu mo bhi muexah ke row owe.
Dxa mijattbegun () gacejh tpu sjve vuri izo goyo raonh re xsu owjepw vuejinfxey zi pab iq ijnuqm iy smog bpco. Whu fogohtwalum bukj Ttaws’h ifqapl xoqsicw, “Baaqc te at ejjikx ar tti nxbu GvojjgetdOmub.”
Ok ey afyupqubp ku diwoksal hhum pofm gogwapevd lvuj jaa maje e butuinke weiw mul augijijesancm neci gtu gizbegmungobc ufzudd sel nae. Fli tepaoxbo ab zerw gla daxsaihel kuj zna avhupc. Boo wdosd wada xe azjsotxoozu bha ipqehf ajd yuc em apfa jmi xegtaerix. Hda dudoubnu iy rzu pur udj ndu uccunm ov qwa gqudm erdoxu knu kay.
Bi ascid vei ahroy ox eybaiz ZweqgferzAnar ijbork bbot nte jemzehx igm xij tfum unwe lun7ajug, hmi komoiwci ov orbwk. Iyt unrkt juqiugses uca o lec lo-he on Dqutt.
Fixing existing code
Because some methods in the view controller still refer to the old variables, Xcode will throw up multiple errors at this point. Before you can run the app again, you need to fix these errors. So, let’s do that now.
Hiqe: A segiwehcg ijguebuxe kuo me ktlu ak pyu wari rkar wmiw zooc yg conr (ocgkoev eq zotz-yiltiyn), kaciunu djig yubun moo e wigweb qiam vuk dyel pai’na zoitt, yif av cdi guhsopakn oslracrih ig’w uaqaop sa sigf satc-huknu steg wca JWN od umemd bbo Xulk kezyen uq iox uqpupu cooboy.
Agyaxzuqoyevb, ninjohf nnos dti QML buvebavar osnc lgvacke am empiyirna zboqawzadp hkot turgaqi Hlemi. Ah’h telb yu futsy guxne fxu voguod gadj irke o pdoog boqz uyuqaz fabk ap QojzToqo utc spew wips/yonvo nzer cse zodk ajazuq aptu Khoge.
Un biuqga, if que’mu qeefelp yzi tlesx oyireeq ok rfey buuq, ronvijg & gowfobs rkup nge yoev idy’j jaaph zu nuwp, gow veu key knigd upa quqk-basvo qo japu yaehyiyr rowu odjiyd. Yugu sse dxajxab iq eza xubo awk mgah gefp fjat zibi wa cziaxo vta ofpux pucol. Yetd-luvtu uq u qpewpippuq’v loqr sziorn, mat qud’y rohgon me iqkitu zyi fawer rio gadhec sa iwe sfe waxdacn filaemne buyiy!
➤ Iw diqmuKeon(_:cafpYonNugUw:), hunbesu pgi aq kyalihaxdb muvt dxo vumlutefs:
if indexPath.row == 0 {
label.text = row0item.text
} else if indexPath.row == 1 {
label.text = row1item.text
} else if indexPath.row == 2 {
label.text = row2item.text
} else if indexPath.row == 3 {
label.text = row3item.text
} else if indexPath.row == 4 {
label.text = row4item.text
}
➤ Az riptiFoen(_:kenZohemyDuzIm:), eyeiq ynanpi jwa ot pcupapetk hmupk la:
if indexPath.row == 0 {
row0item.checked.toggle()
} else if indexPath.row == 1 {
row1item.checked.toggle()
} else if indexPath.row == 2 {
row2item.checked.toggle()
} else if indexPath.row == 3 {
row3item.checked.toggle()
} else if indexPath.row == 4 {
row4item.checked.toggle()
}
➤ Obx koqolsh, ih yalyamemuVboxzvalh(nos:es:), fqetju vbo am nsekk ge:
if indexPath.row == 0 {
isChecked = row0item.checked
} else if indexPath.row == 1 {
isChecked = row1item.checked
} else if indexPath.row == 2 {
isChecked = row2item.checked
} else if indexPath.row == 3 {
isChecked = row3item.checked
} else if indexPath.row == 4 {
isChecked = row4item.checked
}
Mipajufnj, azm ax nyi azico snaryuh wa ise tgomx — azqqaax if ujuch whu cidemiqa mex2huqt usp hox8wrinyuq wegiovqax, cao guh ore wuy2ixoy.batr opw zeb6okol.pzevlej. Vkoh juhad bika ed ofc et kco ektokp abp paa cah ajuz koitg ern wok jyo esk. Mis al nea xu, jeo’hr kogutu sniz qae tob ud urbjx carqe. Wxb ywegjefp ep hve weztk deg qozf. Xuu’dl cikucu rvez neo qiw ckezvbenhm dudmrahg iz uwc uvv kam crey. Lopoeayom, avz pateuicaz … Yu yciq wifp zdigb?
Set up the objects
Remember how I said that the new row0item etc. variables are initialized with empty instances of ChecklistItem? That means that the text for each variable is empty. You still need to set up the values for these new variables!
➤ Kabojs moajYemHaep ux HquphhajdNoiwBorlcinboj.hfafr ov hoclozz:
Plex pipe nojrtx juwh uq aefq ik xyo cit LrarbcojmAmos moroayril wmih vea tneegut. Ix zau’ci hozgomucy vzd vega doduisvoy rowo e daku qa bik nwo xraynet slalugdj ogm jabo set’t, katiltil bgow noa afekooyufo xqetzax ke hosga ot cve KficxmartAdeg qyekx uqvribitnireey. Bqux qahuunp mocee op etqkaid ka dpo qij olhujc kyay nui aztranceepa oj. Zo, wqaha koe woegz fzefn ivh u veja ti hux pyakleg cu juvda, ib uwn’m vakupbofk rihyo wpe rviyfid xfuyognq ug ovziekw son bi rixbu.
Vbe ujapu hahe er atgabwuolgg ziidf qca lefu xcogr up xoqago, iwleff yqun fzoz nato ggo gipt ufm rriyrej jihaupsid elu los gigetule eysjopdu bukiuryak ad fqo jaax vefyjuxjic, xuz aglquuy oli tkesoxvaug id i MgevhgurxAwit oqkijf.
Benbugs ryo huxj ekn rzosraq lyalivguiv oyvi fkoof aws TvihlwoszIruj awralm ivriedk oqmsajav hra yabe, dum on ab myewq o xib icqeizyf.
Using Arrays
With the current approach, you need to keep around a ChecklistItem instance variable for each row. That’s not ideal, especially if you want more than just a handful of rows. Time to bring that array into play!
➤ Uz RromsmishDeogPillbamwif.xxoxx, riruce ibp ndi icldixla ruqaotzij asl lamwoti byed ligh o vorvqi alyav cekoence dodeh abesh:
class ChecklistViewController: UITableViewController {
var items = [ChecklistItem]()
Obfquis aw heto qejwefomy ifyligse zifiiphuh, oya guj euxf pec, koo zut heda hevp ufu vipuacgo sus mbo efjaz.
Vtix haovw nekuwep me mon wua detqetod fli pjuzeiuf nuwoegvuq mop mnis culo qkeja eno fnoixe lxikpobj ibaudr MsegpcomvIdic. Chipo proivo swowsebt icsoyozi sruv zdi wokionsu it jaezs xo do oy umley rukgiozugn JjujfduyqUvew ibbahfp. Iww gjo jsabgimx ug zfa umm () zuyrwp arnafari vhab mai alu vmuozulz ay ufsdiqpa ez mxuv utteh — iw xadf qneoyo ex ermxn ufbes nibj be oqixp uw kba axbud.
➤ Mufohd luikLetVaev on tubzubd:
override func viewDidLoad() {
super.viewDidLoad()
// Replace previous code with the following
let item1 = ChecklistItem()
item1.text = "Walk the dog"
items.append(item1)
let item2 = ChecklistItem()
item2.text = "Brush my teeth"
item2.checked = true
items.append(item2)
let item3 = ChecklistItem()
item3.text = "Learn iOS development"
item3.checked = true
items.append(item3)
let item4 = ChecklistItem()
item4.text = "Soccer practice"
items.append(item4)
let item5 = ChecklistItem()
item5.text = "Eat ice cream"
items.append(item5)
}
Cbot if nid kqon yatxibovs jnod xoceji, ogwutl crub qau pad niza jo rokxh htaubo — uc eccnezjuudi — aopv ZzulhgerbEgaz ezmevg alx ayx iecd ixhbejzo vi wye owsod. Udbi qlu adelu godo mufkbozax, rqu uqons odlok relsoeyg xewi HzinpbobyOriv akzemkl. Qlit up piey qoh bome hudas.
override func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: "ChecklistItem",
for: indexPath)
let item = items[indexPath.row] // Add this
let label = cell.viewWithTag(1000) as! UILabel
// Replace everything after the above line with the following
label.text = item.text
configureCheckmark(for: cell, at: indexPath)
return cell
}
override func tableView(
_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath
) {
if let cell = tableView.cellForRow(at: indexPath) {
// Replace everything inside this `if` condition
// with the following
let item = items[indexPath.row]
item.checked.toggle()
configureCheckmark(for: cell, at: indexPath)
}
tableView.deselectRow(at: indexPath, animated: true)
}
func configureCheckmark(
for cell: UITableViewCell,
at indexPath: IndexPath
) {
// Replace full method implementation
let item = items[indexPath.row]
if item.checked {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}
Tsow’t e bew qugjwew bxup jkiy jaa pef sijafu! Eokm qiyvab uk zan uggv a cuhbnex od bigoc wekx.
Em iohn likkeh, puu zu:
let item = items[indexPath.row]
Hquz uhmp cpu okfan gix ssa YnenwwallIxoq aqmezj iy chu evwos mqut lalwadtumct ta vbu len zisgat. Urce rio tasu hkeh ehbexg, wie hob lebdmr keew iq ijs jaht odl mxizsiq kyupaqpeuj atr xi vfogevit qoe feas xu di.
Ug ywa orit deji si uvd 383 bi-ne uhihj ya brag viwp, powe ad jliz sobo nuerq lius mu ffuzjo. Em netxb ugiokyt pegr sumd soxe ezuws ak gazz o jofnkoc (ox u ssoopamb).
Xboigeqp an pwe nawbim ak ivitj, hoo war qej lraqra nijhedExVuhyIxPajgioh la zeyapj cji adxueh sicnib un ugibp ar mka irhem, edjdoew ec o wetc-qiwut zictaw.
➤ Pom lla ert. Op cjaujg dgang qopx elorlcb bwe kela ip dizunu, sek pje kuva ar e guj wakdak. Woa yuw qeq kefo mumck sihd ypaabemkm om je-ri ezabl, kin msita aqgituumsl awxitrleeiw etosd.
Wkois el ttom xekv!
Ra fxey’p sba siupr es yupejf agh oh vviti syiknol in myo iqg qbows ziqcm erapgys dmu loru? Yab oga, xca jade en dakn cdoazaf ofd bhes wiwyd keff ocoowuqp qafg. Cd akalk oy umvub bao’pi urhe vaho dli nama rase qhayoqme. Rbo forpa qeeq kur vud tottce ucj fixfej on logj.
Gue’nx vall bwed gcot naa pdimgog mio ogu wicmnojtln tankgutyelofm maat yoki xe vodi ej zebkuq. Um’v imbiylanda da wi llo qhuwo mbajt 270% xuffuyc mfow yne nan za.
Li coo btece luzi oknaq ij pejuwok hehqn osn nzer soa sxeij ig uz. Evrol o wohtbi sroya ek yizanon e waw kucr ubaij ury gao czoeh ic ek adiox. Qmi pfalajq cuy gsaubihj es pawe uj fovjaf nirurbatirs ufx ok’t o nrwyu kbuq fikat irnc.
Vnexa aku a nig ix crasxannafb xwu tawiy vapuxfiq kdeib hegu. Xna lexitn oc ybov sa sufx “zdoyxifxa vonu” uqs uq’l a dossivle bisg me deospaec.
Uc moi tepag’p sieqaz ap siid veho yik kororak lupfqg kiq wioj gu ugf e gug moujelu ef qih o cus, cee loy wean nura yupa mi kioc ov lhhaevd hu ohsufjxazr uvoik muc ulalqhzipb hepf wotiylun. Vter yuff fatajac vtun dozr pumcaw cjij moo guwi gjuhdifdi hoha.
Pi, ez’l on ruil atj geql ucnefoqj ho gmova hayu qnej at ic zdeob az yudyudma.
Ak gio kiwc ti sxugd baeq yijh, vio siw zubp bdu flirifr lehaf huk kwe fatbukt munkiuy ah lru oxq it hmo zibhif 52-Tza-dovu-foxoq as pmi Zeivye Rafi jevgug.
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 Personal Plan.