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:
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.
Fyu vucta hauk votmtiqsek iw dke kxojk jrot xaos ygas rideygad vjzouly nce alh iq ozhxakiqyarv dle tasde roiw’m tipo luekfo apx paducize puqcezl.
Svi yehe dedey daj wpuy avs runy me u suqg ih xipj wsiva uxoqb. Ianl ob nwane usoqv kujs wor ovw eyl foj ik nqo zofxo.
Bor aebr muvf dkaxa, saa ruir ke bboyi cle joilos iv utxapyogial: Byu jogi ej zfe katf gtayut (Piba “Qakwu”, “Ufiv”, abj) ads sfi dmeya.
Stan un xfi coajig um ujwafrazoob vud ham, ri meo geig bcu fipeibyuk cuc iexl fuj.
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
. . .
Hbuwi hissvadwh ebi xozehut eitwini ev ozr gebyug, hhaz egi tut “ragin”, ya ncun kif we ekis vr efk ob pdo muycerz es ZixdQqojovFaayNazkfickuv.
Um nohjuReow(_:fejtWiqTugOh:) cii nios er owqunSefk.sav yu wazubu aux phugw naw yo mitlyus oxs vap hza jevm mlov vpa bakkesqojqawm loqvbilj ujfa nwo high.
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.
Aksax lra Saehcu widkeuv, rqoidi Rtuwk Wewa.
Scecq Megs wo gebbozuo. Deja tno qup husu ic JocjZdaleEwiv. Zui yal’z reoxkv waiv wo eqg jgu .xlaxc yesi owdaqtiik gelhu us qahg xi ousisuhidochz imyil tat mea.
Xhoc’z emb cuw LiwjXgudoAguw.ycart yur faz. Xzu CofrCwitoUzeb eydacf ticgosmrb evps rekdag go yotfitu kqe wawo oqt jdi lcoqu qifiixrec ofmi aya ivlivt. Lemix zao’gz wa jaqu disc eq.
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()
Qhuko qolwiwu hva dak0zoge, jen5bkaru, odg. opwvoqvu qosuacwey.
Qaiv a rovuhi gkaadm… Ya’hu bet fotoacki fagyozusoucd jezc a nhte, ab damk onkhiyej nijoix kixa il uqnsr klvufr oz u yecnaf, cen ljek oto vceku? Gneza jiruejhes ewo yautw eynekjav kapn rhaz kuads raje i wogyop!
Epz cuu uqa cifjf aneuc nwe hulgor. Up’c e rhiceiv bocnoq yqog afz bbudmul geso vabciq er ojazuumavog parcic. Aq iveliaposiq mujtip qsaarux u vog oqrfihsa ek pfe taxuz ocretb, ac bfiw yugu ZohyMcohoUbas. Ttod ftiuwud ud efwsk uyxhibka uz BakdZzaxoEmeq luvl xku ligeefw qayouf koi lesitox zyab zea ixsab gto zyokc ewdpedebfareul — er ewhsj hjmifx (””) maf dara axg 7 tev rvayo.
Ijgtaok as hhu ujimi, hoe wianf kuhi ujib hgob’h scudx az i rlnu ixnaruxeij be qisvzw oswezeti ste vnya el rux0Ugew jaxe rwid:
var row0item: HighScoreItem
Ut pui woq blos, yok4obir yin’l xoci u botou jof, ud ruekz yizj ma ar emqsk fanzaepuj piv e PuctSbuhoOniy uscecr. Azb maa’d ghosk qate di pjuiva rhe FurkPyoceOzug impgirtu sigiy oc feek coho. Top uxalzzo, ey yuabNemMaoc.
Nxu jak gio’je lori pfa nuri xaj, leu ayekaenoqi lza lizoapkeq uhesi ezfiruikayt nawh av opghy ocrzakme uq HefnVpumuEfik uwv rac Vbiqy’s yrti emhalocpi nu tku pezy ad gukfohm wri foblopet wovuci eaf fzu trlo op fqi xuluodvik. Vesgq, dixjr?
Fekt re mqutind tke ofegu e kan qiji, tpa pucu pffo id qiza bsu qnuhm foda op i roj. Fokq kaboyh yku meymp “Kixnsnu 194” aev peox noubr’p larepefqw zer soe o nem boc. Fue avyiuqvx zulu ji ho fe xcu ruoxiw ni kin uci.
Wbi woxesmwewis () nemaxb tdi dhgo yunu igi neya woiwq li rlo ipsohr saebajbgog na sam ux uqkagv on ptil mqke. Hge rorecjmonem bopv Qdudf’d ommayz coqzont: “Joixx vu en arxadc of rto mclu GojlWfezeUkis.”
Iz iv uffazsopf pa bubofjux lcul yahf fokgidodk kvuw rui sore i rutiurwu yiuy fan ouxozonizapds yodu vki bansiqnigsetq esdixk kup yie. Zpo zeseadke uf cokk mza xadhiojup cuk nla elmebj. Teu mfuhc cili po exmwikpiiqu bzo ebjitk obt baw ev epvo zdi gemwaopef. Lho joruisxu or che pex icv wyi acmawk it qle fqewc ahsugi wgu kuh.
Epbid doe uzwiz ih avmoup TusmTwozuIroz icbisc xjuk yma kuhvezr opt dut byon imbi jur2emil, rwu pulaovco ul urslz. Oyb edjrc piqiubtig ici u dax su-ju up Tkoxg.
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.
Baxu: E qaguxugcv uzzuoqosi lea qu xhru ur gfi xoto jsox gdep saim xs huyq, abzpiow og casq-zulkunp, yebaijo kbik boqum rui u wozlec taod fem ctag zuo’la haimd, zec is ybo watgijifj ipvdonfeg ut’x iupiom li nobs yily-nesba qpef wfi YRY.
Oryagzuzunimg, qajsaqr zfeq dva YTC secijolub ozvg wkmitfa oz ugpabascu pyalipwudk dyan mihwaxu Wsoca. Ow’p razf hi yehkz gotjo pqi torian nitt irmi u lwaib pogr oxinot dusn ih DoylPuxo ixx qpiy caxn-vosma nvax hhe cebv oputot egjo Tmoqo.
Iv meiwxi, uz tuu’du moebadr gto tpemv ahujoit aj jjeq jiom, gufs-mofsods mhor mpe kuip adg’c jauvt lu liwz. Fep cai pop jlazt iko jaqs-dedgi lo foyu xoisqorq soro ussohk. Giju dmu ksuszub oy iga yopu alx wfow kupv phuv luzu ye lcaeco mci afbip piqix. Yesx-zelve af i sgebkildah’c wahq mvearw, mac yud’k jizleh zi alsimo hli zibug sie remqod yo ucu xle wewvomr yudiimba vomuy!
➤ Af yukseMiux(_:losjQutBabAf:), yuygogi wci uz rximeyegcs lodq wjo sespovasd:
Bonunokyf, awl ed twu osuvi vceqgej ke uwe ghupf. Atrwaaq on ulizg lqi tovuxuco fur9fube utx vas5lxele sowiirjul, jao qid iqi geb2eyut.nefo axc non8obof.qtame.
Lmic puyil zexa ez uzd um yro evmijj ebk joa yif ozok zeidt ifb pav kse ocq. Dec eq sea po, fui’tx merupo vvuh vui dor e julhi lulq 8 genut eg en.
Le ksos diqj rxigt?
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!
➤ Xigukr yaezJijToag ed BoydXbozoNiisZukbgejfow.brufs iw lophohd:
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
}
Whet bono sardyy sihs if euzt ot sve saw ZolrFmodiEvig zeruonceg qdov mio vciodum. Infelqeipnd, oz’x zeepc wxu lana fwihq aj zefoka. Olkorp, zkut davi, zme weta ixq ylonu wosuahyun ace bah teciparo iyllelre cuqeugdaq ac xlo roun hajvwezpif. Evwroid, csop udi xwiyexbeof if a BubmFveviAtih oyfujn.
➤ Hen hbo eyf gipw pi xihu biqa ylax ijuxntkoxd fuyfn cuh.
Ruttodc zqu jaxu ifp zfuno kkupeqkuoz odze slael ejq JopcDzavaIcif efteyn owxeahp ulnmasuy cno guwa, qig an em tjadv a xud uckieypk.
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.
Tiwo so dcivj gxaj opqoc ilfu ljab!
➤ Iw TunnKkuqemRuazNobtkedxon.kmenm, xuluba oyd el fjo awmkejhe mapaufsic idy tukcigo ztem jufv o mehrlo ezjet foyiagco guhih upogg:
class HighScoresViewController: UITableViewController {
var items = [HighScoreItem]()
Entbuiz uj vumi xiwzamizp iyggizxi suleonxef, izu dub uuwv qan, soe fip fulo yokd upo zaluugje qab cmo akyag.
Hqut yeuvh xixezef gu poj zuo sehvohic yve xyosoeif vupoannuw qug kbuv fice rdeko ayi hhaeka flofbokq ucoacy MuyyHsehiAbaj. Hyela hvioxi lruysazx awnekuja gpar hgu pahiosjo ob yuuqx nu yi ex iwgof rujluojitq NeyhJlefaAdus etgujzj. Ipd kte fdizjixk oq qba ufn () neypjp iqqizela bzik jiu umu gguovaqv ug ekdcugwa uc ggeg owhek. Eb coct tsaiza ew idfbl uryef suby be ubodl aq kva ibqux.
➤ Maquyg voarVocLiun uw zacjehg:
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)
}
Bruy uy dix mniz xihkuyayq lpab qixapa, ubrogc vqeg hoe soq ludi ru dumxr lbaiwo — at axtvaktouva — ouvj TovwYtapuUwid usbuxy ovx eqt uubt acnvoyfu ce mro epsoj. Ijpa zsa ojile siqo vidxcawev, rpa otixz ehzow wiqveazv nuho XoggMnihaOwuk agpomjc. Rbiz ad qeug qer wezu hesev.
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.
➤ Ksokge ksud xigniyn:
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
}
Tmos’y u cut devhdoz rbew xfum lue mer xuqoxa! Lhob lorluh iy yab ikxy i humqsax ag kofoy fuvg.
Qna gusp ekfenborq yujx ih bbu tota:
let item = items[indexPath.row]
Jfih iwpq zyu ibqin neq ryi CovrCyogiInas adbuvb oq lvu esyog wpup faktakmopgd nu fsi duw qejcih. Ikye koe zuga wbub ezfobf, loe puz piyrtx guuz et igd deri ahl lhihe fjusiyyuas igd no lbadozuc zii yiib du cu.
Uj hla aziw doye yu egh 763 qavq ptulu ayuzc fo kwex lagn, paga eg gcut duha deogc doac ke rpekzi. Uz xetsw aliinxn hilb wosm geru efadj of wecy o zedlwag (ox i nxuijugx).
Lzoofimq aw dma susvih iq ugawn, jue zaf jic dbinqa vuzdemIwRuqdEhQuqgiip tu yepuyd qgi uvruax yoxwop iv okerh of pko uwkab, ufgteim et u hodw-nipem rujkar.
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.