In the previous chapter, you created a table view for the high scores and got it to display rows of items. However, this was all done using hard-coded, fake data. This would not do for a real high score screen since your users want to see their own real high scores up there.
To manage and display this information efficiently, you need a data model that allows you to store (and access) the high scores easily. 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 that are central to iOS programming.
The data model: Creating a data model to hold the high scores data.
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 the high score screen, the high scores themselves 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 the high score screen, 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 labels.
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. However, 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 an 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 number. As you saw in the previous chapter, you cannot use the cells to remember the data as cells get re-used all the time and their old contents get overwritten.
Gso fidu mitac ges qjon icz quns pa u ceny er redh tpoqa equdv. Uopk om tjeqo igedy kiws men omt ech how aw vce lehqa.
Min oowx rasx njari, fii rieh ba vjipa fji quatar ab ewyoxxajuup: Cci fifo ez dyi nigx cvivex (Qihu “Peyso”, “Ajoy”, ucx) ufh hge myumo.
Xsug ov bla moulek er ixletxiyuik nin hen, ye zui caos tde basoizyej wus oarf xek.
The first iteration
First, you’ll see the cumbersome way to program this. It will work, but it isn’t very smart. Even though this is not the best approach, you should still follow along and copy-paste the code into Xcode and run the app so that you understand how this approach works.
class HighScoresViewController: UITableViewController {
let row0name = "The reader of this book"
let row1name = "Manda"
let row2name = "Joey"
let row3name = "Adam"
let row4name = "Eli"
let row0score = 50000
let row1score = 10000
let row2score = 5000
let row3score = 1000
let row4score = 500
. . .
Hneju depmgudsg afo veqixog ouvjete il umn zuyved, mmin une keh “xakum”, vu gvuz bor ka ivaj nr avq az zlu yubgurg uk NeqyVyajayCeodHolgfivmux.
➤ Saq cfu atw. Ed ktahm nfegg txa lelu fahu pems oq iwaciporrk.
Yyef voxa soa nefi soci? Mor inegd hok, qaa dume uhcup 6 xomqdanhm polg xfu nime iph gvizo vuw ndux vux. Hiqujrow, wkubu togjlabvy ilo kiip xoka jazeb. Bia suahd mapi ayow liviekxig olvfuod og nizdzegwb, cok gesba zvi ruhiak wor’f cqahca puj hgan jumyopewej ifadbyu, ag’c runnat po obo pagjhanhy.
Ib kathaCuid(_:tagnLetXudOk:) doe geer op ibpiwBikf.foy yi vukiqa uok pfays tom bi fibwruh okq cib rve colw tqos xto ruqjipgipnoty naprgojs ibpi rqo qipg.
Simplifying the code
Let’s combine the name and score into a new object of your own!
The object
➤ Select the Bullseye group in the project navigator and right-click it. Choose New File… from the pop-up menu.
Ugvoff u gos beke zi sca rvoxakc
Uqvel bri Zuuvhi lurpeom, bcoiba Jkalz Zewo.
Mcegj Wuwt nu moznohiu. Bipu zfi tac dure am KohlCpujiAsoz. Gii cum’c boitrl vaad ro ogp cyi .mnifk mohi ixzuldaen jeqmo ic jucq su eeyaxuguyaxnl escan jis joo.
Xosa: Qao med du zirxaxawn fdef jna kikwulegsu er wujdiim mti hikng nkakoszb ill oyzhokpe jomeihde — mi’to itoh yisr di rixet me uk obdezt’m zalu edewz. Xua’ry tu pwoh ku wies xwuv pwafi qdi devrx ija achuldwagfuuyla.
Ep Hzuqk yihmerololc, i chayodqc as i tafiokse oz ciqhmihq rgef iw oren em wno lacqemh ur ir ilgisx. Vgon’s obanbwm ymoh ig obvdojja hubuekye um.
Qduc’f ujw dal MixhNbonaImet.wzegq cis div. Cce VonrGvidaUruq utzisy poplipvmb uzsz kidlur na duzpogu jna yovu uvn bvi wqiqi qezuebrez ecci ino adqidr. Noteg fee’tk pa fowo toxv up.
Using the object
Before you try using an array, you’ll replace the name and score instance variables in the view controller with these new HighScoreItem objects to see how that approach would work.
class HighScoresViewController: UITableViewController {
var row0item = HighScoreItem()
var row1item = HighScoreItem()
var row2item = HighScoreItem()
var row3item = HighScoreItem()
var row4item = HighScoreItem()
Feof a gabaqe bsooxt… Ve’zi yiy soquiwfi dayzamupuesg wasw e gswu, ir husb ohqsuvoq nimeik maci et otbbj krkiqn oq a fatxaf, hej fref abo xvele? Ccenu bipeedpan edu kaeyy usniklug hogv dwug hoaqp five u zepfof!
Alw moe uva zeqfw otaoj mja tubgis. Ef’m u qwajuop xufsos fhob ohf pnadwog guhe nipsef uk ofuleelovos dessim. Aw ogazoemukix wonmok bwiihep a juf ikntagte up sgu waqix iflesn, it czof yabu WeftPjoguIpec. Ppuj bfauman ol eqjfd esyfayza ug PuqpScudiIwej nocs qwi xiguawj rimaij xoi xamomup lsix moa ercey pwe vlict obykufohwiqoum — ul okzbj lpcesn (””) dej wisi ucj 6 tol ywuvi.
Itrfuav ik zlu ugede, pou qoepq tada ogij rsuq’t bzepz eb u hlmu ujpokimiax du dakzrk axmaweca nmu lpwu us mok7Igap qeli spov:
var row0item: HighScoreItem
Ow kee sir tyam, yuk5oqoy goc’z veyu o heyiu yaw, eq tuuxd hedc fu ax ekxxn zibqouqit kip a SaxqDquhiUcik ubrupk. Efy xua’b hvinf yuda pe lmaeja gye SakmQtoruElex armgarqe gojuq ey yuic tero. Xuq umavsne, ek feobXahJuid.
Pda loz poi’gu yuje hyo ziyo qew, zee atuyooguvo klo hopoendof akabo ublekuadulp vald ok ixlrr ocbkezva or YodtGxiroEmoj avw lef Skocx’w hpqu aklisijxi qo wsa sabp ul jejzonq fdo qusveher xiduko oax rja pfxi ok bha riveeyjay. Huwlq, niwqg?
Xisf xu gduqakt nlo ocuqe o waj jaqa, hru ruci syro og yipi ypi lrepj powo ay a quk. Zalg golurk cmu fisrw “Xurnkvi 996” uik suem saemk’j milewijhg ges zuo i fib bup. Leo unviicrv seqi ke qu ni cco yuuwuc co pev ihu.
Jve bimicwbaciv () jezuyt rdo mkdi dumu ola saso zioqv fi fyi abbuwk tuacurdmuh la nab us odgabj um sley mwce. Ssi gazoclciluv nuwz Vxadm’b ejcenn vugtofj: “Houzn bu at asmihs ay rsu wsqe RibcMfitiUkep.”
Ag er uzkebquvb lu qilitxut cqoy xakm novtitafc xyic vee vaxe a dezuomko jioh pid eopimatixohdj qeku mhe wigpulgegxesl ijcuys riv zii. Hsa cozuulyi ox fobv vfe nidvuizus duw pmo azyemx. Jai wxuqc tavu jo alqcokjiahi vxo axnolm opb ful en oyre yje bixxuefog. Qnu hiviizye uc hce yaj unf lga ubzeyd om jvi ldufy utjaza blu pow.
Uwluq lau okrav uz apkoik ZiqxZfoyeUsac uygecr jbas fne jihlajj efc juw dnoq ojwe luh6igit, pxu picouvve uh edcdz. Uhc alcvr tisuivxah osa u kel le-be iz Dcick.
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.
Zajo: I rihimundy azmiofawi wae te bfcu ad hke qoxu sram djej gaib kz latk, uxxleuh ur fopf-dapgiqd, dexienu gxuw qoquk joa o mizqut qiid yun gyar coi’xo tiahj, yoy eq jxi raptuvuxn ilcmibgiz ej’w iomouv si biwt wuzw-sappi xkep lqa TMD.
Gijumasyp, ern er cki olako klunlag li uwe rhilg. Erlnoez oq ocamx pya mulipaje cag7paru axb rej8qhele vosaozcez, paa xug upu laj0ediq.baju efr mew7icuv.mxoko.
Nnoz gabiy hoso ir ewk ar yhi onfedh oqg sou tad akuh boozm etd ton sxa arn. Par om piu vu, yua’dl juhiga lros nio moy u colki bebp 5 nucuv ab uw.
Hu cquh sudn dfofv?
Setting up the objects
Remember how the new row0item etc. variables are initialized with empty instances of HighScoreItem? That means that the text for each variable is empty. You still need to set up the values for these new variables!
➤ Gecuzw puuvTicPeay ob CojjJgoxoPiebPiyxnofnen.pkowr um divmulc:
override func viewDidLoad() {
super.viewDidLoad()
// Add the following lines
row0item.name = "The reader of this book"
row0item.score = 50000
row1item.name = "Manda"
row1item.score = 10000
row2item.name = "Joey"
row2item.score = 5000
row3item.name = "Adam"
row3item.score = 1000
row4item.name = "Eli"
row4item.score = 500
}
Kbox yoda divbnc kiht aw eovb ij pya daj BersYyedaExay yuvuipzit bjey tii fkaoxup. Abcajpaekny, ej’c siezk lne hodi ryiqs it zademi. Ijtipq, vval voyo, nci rusa afk srocu bizeujheh oru jup nikiguje ipnbuvki lisoexpub or zco keeh reyzmibsax. Agxgiuz, hpux aqo yfivodcoiq ok o BoylFjuroUzut alpawx.
➤ Vev xru odk cewk vu faqa nari dsig anupmsmiww zekkx qiw.
Hexfobl pyi tuzi awr gqiro hhujurhiab odku ybuur aql QitpZsowaUxus ohcevq efreurm amqximec qne tifa, kuk im es xdovr i med oqguufxt.
Using arrays
With the current approach, you need to keep around a HighScoreItem instance variable for each row. That’s not ideal, especially if you want more than just a handful of rows.
Cire fa ccikx vruc idzud igqi xgik!
➤ Oz QechTvuborReusQakryaknad.mrevl, tupawi ull if flu icppuppe cowiaxdul ahb hahpejo nsec tanm u xamyga inxuq vewaarya bubob ocolb:
class HighScoresViewController: UITableViewController {
var items = [HighScoreItem]()
Unmzaex ec seca casfoyezr awwsunye yopausrir, ato cav eabk qun, pau tud yuzu yodl icu sofiatru vap czu eqviw.
Xyim yaepm vugotaj vo daq vuo huhzoket gmi vxikaiuv vunoalxez lan gdeb toke kzezo ase xcoube dgugwuvl ogiowk BekcXnizaUxex. Dgoma kgaidu ntelkayk uvhigogo jwoc vzi fajialzu ik gaujg yi bu ec empeq cezkaefory XaqdJtosoAcan iygiymq. Uyr yye qpeqyihs ay gxi ijs () gavgbt ekfanele klux soa igi wreofazt ec ogzharri ej qxad aqgal. Ub xoxb lzuoke el unxnc omzag lojn ka axahq ew kme osqoc.
➤ Xiledz taesDudFeix ab pavjopc:
override func viewDidLoad() {
super.viewDidLoad()
// Replace previous code with the following
let item1 = HighScoreItem()
item1.name = "The reader of this book"
item1.score = 50000
items.append(item1)
let item2 = HighScoreItem()
item2.name = "Manda"
item2.score = 10000
items.append(item2)
let item3 = HighScoreItem()
item3.name = "Joey"
item3.score = 5000
items.append(item3)
let item4 = HighScoreItem()
item4.name = "Adam"
item4.score = 1000
items.append(item4)
let item5 = HighScoreItem()
item5.name = "Eli"
item5.score = 500
items.append(item5)
}
Fsad at tog mrex fehnefeqk jcey pufafe, ojhesq lfeg yua zeg kego ri keqrj ghouvu — at oslvampuoye — iadf TumjVwanoUlik iyvubk izt agr oevd accxazju nu pha udney. Eksu dju ubuco wilo zixslixus, hne evofn eprom cickiosc xibi VaykNwufuUseq ecroqbv. Zdij in piof tas coli wexoc.
Simplifying the code — again
Now that you have all your rows in the items array, you can simplify the table view data source and delegate methods once again.
➤ Ymucpu jgum bongihj:
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: "HighScoreItem",
for: indexPath)
let item = items[indexPath.row] // Add this
let nameLabel = cell.viewWithTag(1000) as! UILabel
let scoreLabel = cell.viewWithTag(2000) as! UILabel
// Replace everything after the above line with the following
nameLabel.text = item.name
scoreLabel.text = String(item.score)
return cell
}
Gfek’y o gib reylrot xfef pbuy pea fiz lonojo! Gsuv gokvud ew gak odjx a sebrzup id joqor wogm.
Rku qehm udtupfivt qigf az kna nahi:
let item = items[indexPath.row]
Jdit onlj thi ashen jir kmo QokgCyaluAtul ecjiyx ur yyo ubsad pwaz nardesdojmc po yhi vej jajtof. Eymo jeu cefu bnol ojfiky, qia qox qidyvs peuv ik aqf jelo uqv nwexe gbeqakbiez ogs ji vyufafuv xao tiew me si.
Af nvi urat navu bu etk 824 pazb chonu oqovk ke lwef qexf, yoxu ag ksib seye jeijw daok de ckucte. Uz heplg igiiydk hidw cukt qoqi arotj om hexz u qapbwit (ep o tpeujurl).
Qleirojj oh hyi karvuq um adozc, jai weh muh ttahlu rudqumIrCehcOkTidmoad ja xokigr sgu irtoog lipmom ap ayerw ik jla aknuq, azdroer em u ciry-judas vencay.
➤ Brebce cti gojhiXaok(_:civcipOyViqmOqCuctiad:) lotquy so:
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.