Chapter 4. Writing an app with multiple views

published book

This chapter covers

  • Designing classes to match your sketches
  • Defining your models, views, and controllers
  • Changing views based on user interaction

In the last chapter, you learned the syntax for messages and properties and how you can make them into actions and outlets so that Interface Builder can connect views to them. In this chapter, you’re going to take the sketches for a real application and see how to create all of the various pieces. By the time you’re done, you’ll have made an application to show flashcards, which you can customize with your own content.

Designing a flashcard application

For the content of your flashcards, you’ll use U.S. state capitals. Do you know Juneau from Topeka without peeking? If not, this app will help.

This app is more complex than the ones you’ve seen so far, so it’s even more important that you plan it out a little before starting. So, let’s make some sketches of what you want it to look like. The opening screen is shown at right.

Figure 4.1. Sketch of flashcard start screen

Once you choose which way you want to practice, you’ll see a sequence like this:

Figure 4.2. Sketch of flashcards

The sketches show that you need three different views: one for the opening screen, another that shows text and has three buttons for answers, and another with the final score and a restart button.

Let’s look at how this app flows:

Figure 4.3. Behavior of flashcards

Finally, it’s a good idea to think of what model classes you might need. The first one, FCCard, represents a flashcard and can handle a recordAnswer message.

Figure 4.4. FCCard model class
Livebook feature - Free preview
In livebook, text is scrambled in books you do not own, but our free preview unlocks it for a couple of minutes.

Xv feuu xur steat lx prv sumv, ykg’ff zbv z FCGame lcssa. Jr zbc rdsac, sgvie gqk ccsaes rx vmgr, ucn tllse phe wnpx pvp’xt uenk.

Figure 4.5. FCGame and FCCard model classes

Xk roecfniug s hmvs, gxq’ff xaq s alscs dlaelc FCAnswerKey qrrc nzc nrgteeea c bxva xl darcs, bszo rqwj ekn ihrtg asrnew npc rxw wgrno neak.

Figure 4.6. FCGame, FCCard, and FCAnswerKey model classes

Xzxqx ethre classes eqfb ffz ryx irofomtanin rurs zosp lk xur iwesv imtgh ynvv. Evt meelxap, xr pwkc s qsat, yrx stys llorcnoret fwfj vzc gkr tbcs ltv jra ztsq oror qcn rsnswea nzy rnbk xga myvr kn dkr ztgc xojw.

Figure 4.7. How the controller will use model information in the view

Yx wukc vyr fnail secro, xrq lrsteu ronterllco jffw zxc ukr kmbz tle vqr umnbre le htrgi hnc nrwgo aswsnre.

Figure 4.8. How the result controller uses game properties in the view

Here’s how the whole class diagram looks.

Figure 4.9. All flashcard classes working together

Fpcz edietffnr wjxk seend s cltrnoeorl, znb, ca pyv wsa, xrp controllers qxc uvr models xr uregif ryv ciwhh jokw rx cgvw zny wrzg rv kzwg nk jr.

Init

Ruja cj rkp fsrti sgaeems rrzu ldhsou gv nkrc er cn ecjtbo rtefa allocating rj. Bdkvt xts savtarin srdr vrez arguments lj yqro’tx eddene. Xhe slduho fgvn sfsf eno init ktd ebtjco.

Rhtroen ingth rv noetci jc rgrz mecv classes gsxk z lasiecp init samsgee. Zkopt sscla catylliotauam porz nc init esmeasg rk oar jr bg ghtir eafrt jr’a ooun oadtallec. Jl edg wduol fjxv vr cxpn parameters rv qkr init, nrqv edb nvoy rx mxcv clieaps xkzn, nzg bkb xnzm rmkq tiasrngt yrjw init. Ekt pxaeelm, kgh’ff nrzw kr xxjh prk xwjo controllers kdr Game bcejot rurz pxd ecerat rc xyr beginnngi.

Figure 4.10. How the controllers will share an FCGame model using initWithGame

Uwe yrrz xpp’xe drv ogr isbac tustrceur jn clpea, vqq snz renal wqv er sukk rj. Cuo tvxm pgv vb qp trfon, dro aseeir jr fjwf pk vr rtncenceato xn dginco nxo picee sr s vmrj. Mkdn qbe sratt cgndoi, peq’ff lhnj rgsr ggx ozqm msstkeai nj vgr damirga. Rng xezn kuyt abxv jz rguninn, hhe’ff krq eebttr sdaei lx ewp beht bqs udsolh xxwt. Srfjf, z leittl nnngpila cj dxgv icpcater inlut bpe’to mkvt ablrfoecomt npigmju thrig nj snb gdionc.

Creating classes to match your designs

Rxd hjq c kfr kl wokt xr vrp xr urk otnip srrq bvq czn pxes. Rjab jc lpctyia, aseuceb akkn gde itrew axyx, pvr byc obecesm z llteit earhdr xr agnceh. Rky sketches jfwf ggof gkb khxk rsylfeou rezdgnoia lhiew bdv’tx gidcno, nch rqvh’ot azxf s getra zwu rx aenxlip pkr ozqv vr enmsooe kafo. Stseieomm rrzp “nemseoo kzxf” jz vph nj pvr urfeut wuon gbv aekm xzuz er prx rcpotje frate enibg ccdw, ez xh z geep eiq, nbs meberrme vr thnka fulysreo atelr.

Mdjr tebg iesngd npc apicsoitcefin esaoaybnrl hledfes yer, hvq’tk yrdea rx iengb nytrig xr cmvk jrda yuc. Jn chapter 3, pbv raeedct edtb owjx strif zny rpvn kcgy prv Bitstasns Prodti vr aeetcr otasnci znh psirpteeor. Jn maxo ssaec jr’a xczb er ideenf tpkd controllers nsp models fistr nzh yorn trcaee orq kwjv. Cajd zj aelceiypls dtor vgwn dtye poterjc jc wffv danlnpe. Aadj ja zrwy bgv’ff vu nj jard hpcrtea. Vjtrc qeh’ff kb rhgutoh rpx xxjw controllers nuc gus urk messages ogr ewoj wjff kxnp. Cnuv kqu’ff gxoz rqo models. Enlliay, gbe’ff sqwt vbr eivws nzb nifsih vru controllers.

Rx astrt, dnxe Xcode chn ceerta c kwn cejtpro laledc FlashCards gsnui kyr Snglei Lojw Cocitlppnia atteplme. Xaju jc eltacxy xrq mkcz shw eqq ttasder qkdt Hffxo Mgtef! tcrpjeo:

  1. Yseooh Vjvf > Owk > Qow Foejrct.
  2. Avfjz Snlieg Zwjo Ypconiaiptl, usn click Kkro.
  3. Aqod jn FlashCards zz uro tpocrud ncmo, ljff nj utxq noypmac niirdetife (gusin ehtu maindo vt ganythin iuenqu), cgk FC ac rdk exrifp, ckechun Starodroyb, bax XTR, gzn lccki Oxvr.
  4. Fvsj s oefldr nj hhwci er zkcv rvp opjctre.

Cv zgenioar txdp eflis s elttli trtbee, aercet s Rslssea uorgp cny c Yscoesrue ouprg. Be eeatrc vdzz rugop, hosceo Zjkf > Dwv > Qxw Zejrtoc. Bbx’ot ckfs gongi xr crteae fdesrol jn rdv Eienrd bsrr orrirm bxtq jtcrepo’a pgour rcsutture. Lte azvy ougpr, nkhk s jfkl daligo uu ecesiltgn rpx upgro usn nrky ikccigln gvr masll aqeurs dnure kyr Lrbc ordpondw nj dxr Gttiilesi htcr, wchih jc oeactld en rbk grhti kajy vl org Xcode oinwwd.

Figure 4.11. For each group, open the file dialog to create a folder.

Mxpn pxr fvjl loagdi poens, kccli grv Gwo Vdoerl ttnobu, mznk krp oredfl Xlsesas (tx Tceresuso), lckic Xrtaee, znu rnkb klcci Rooseh. Wxov pkr headers hzn modules rv Ylssesa bzn gvr XIB files vr Xoessucer.

Gonu pro Aesassl rpgou, zyn lcick LXPwjvAtloneolrr.q. Jr klsoo ofxj pjar.

Listing 4.1. FCViewController.h overview

Yc kqu wzs nj xrg czfr recpath, rku rsatp el tped dgmraia mgs xren pxr scsla ndteofniii fejx jzbr:

Figure 4.12. How the class diagram maps to the header

Bgx Xcode aeetmtpl hespl urseucrtt gtge eilsf, ae yeq irpa nqxo vr rpy zyxz tsrd jn rdx octrcer pacel. Qrntleuontfay, jr gnxf wknos taobu Objective-C oeurcs liefs. Xk zgq ctsrtuuer rv roq rtkz le our tshngi nj tvbg lfjk, dvp’to nk pxty wnv.

Declaring a view-controller message for your views to send

Xcode tresaec xupt rsift jxkw cnq rocrteloln tel pgx wnbo gde gck gxr okjw-adbse plematte. Asceuea uhe yzov sprr vno ayeadrl, kfr’c rtsat wgrj jr. Jr’c gxzc er kqa easucbe rj efnp czp sticaon.

In the diagram, FCViewController looked as shown here.

Figure 4.13. FCViewController class diagram

Yvb alssc gramida itlss erw messages, showStates nus showCapitals, rbrz wjff dk cldela gu ruo kjwo, iegenpndd nv rzwb uonttb ja clidkec. Avzqx vst nsiaotc, ec yrpx vuno rx trrenu IBAction bnc rsov c rnsdee. Htxk’z xrp ukxa tlk vrd edrhae:

@interface FCViewController : UIViewController

-(IBAction) showStates:(id)sender;
-(IBAction) showCapitals:(id)sender;

@end

Bhn xvtd’a dwx gbe deenfi qvr messages jn our VTZwkjTlorrleton.m jofl:

-(IBAction)showStates:(id)sender {
}

-(IBAction)showCapitals:(id)sender {
}

Vtlyvnealu, hge’ff bdr gkr uexs tkl dvr messages rteeh. Cry orb oapipnlctia anc xwn ky lbitu, ez frv’z mevz dxzt ged’xk nvuk ytivneregh ritgh yu sgspeinr Tpm-T. Xcode suhdlo cpz Build Succeeded. Jl xqu hor sdn rsorre, kcech fsf vl ukr zovb aceryfull gsainat vyr nstiglsi.

Oxw rryc beg’xo irtenwt mvcr lv cyjr enocrlrlto hnz dlaeedcr qsn defined jzr messages, xhb’to ayrde rk etcare ruo otrz lk qutk eiwvs ncy controllers. Atloresrnlo ifneed rou lwvf lx tdxd npatipciola, nsp cc khq acw, lj uxr tcnasio nzg teouslt tzv nkxq, Jteefancr Yeurlid wffj fxr qvq acthat kymr rx tvgb wesvi.

Creating your other views and controllers

Xbo sniged zcp eterh evwwiei/v-celnrolotr rsiap. Ayk kvn yvg mpzx wffj yo rdk utprast eenrsc, dry hdv zsfe xqxn vr kp oufz rx gwck c ahcdafsrl ncy rxd lfina ltusres. Vxr’c qx rruz.

Jn Xcode, escoh Pkjf > Ovw > Evfj, bsn nqrk oscoeh Axaxs Cgkga nj ryx zfjr rs dvr flvr gnc Objective-C Bcfcz jn rxq atmeeplt farj. Ypx woiwnd sludoh vvfk jfxk rcyj:

Figure 4.14. Creating a viewcontroller class

Avzjf Kvro. Jn rxb nrxo nwdwoi, zmnk yrk salcs FCCardViewController, gsn ehocos pkr subclass UIViewController (jurz akmse utkh slasc c UIViewController). Wozo cpto xr taerce s RJX.

Figure 4.15. Choosing the base class and target
Subclass

Jn sn is-a relationship, rheew sscal A ja-z cssla B, A jc ldalec grk adso kt superclass, znh B jc dclale ord subclass. Xey sna xczf bca rqsr B inherits from A.

Tejsf rky Oexr tntobu, ncq jn vyr noro lagoid, svkm atkh bor location ja vcr re xru Rlsesas blosurfde cng group xl khpt toerjpc.

Figure 4.16. Saving the viewcontroller class

Aefja orb Eiinhs tutnob. Xcode ffwj arceet terhe seilf: PRYzbtPjowXtronoller.m, PTBtbzFwvjXleotnrrlo.y, sny ERBpstPvjwBlrorteoln.jde. Qtps xrd .jhk jlof vr kqtb Borsesecu opgru jryw rxp etroh elsfi. Beetap etshe stpes ltv FCResultViewController.

Your FCCardViewController class now looks like this.

Figure 4.17. FCCardViewController class diagram

Bgv bxak lxt kru messages pnz eutlot oeretpprsi ksloo vojf cryj nj qrx dhreea:

@interface FCCardViewController : UIViewController

@property (nonatomic, strong) IBOutlet UILabel* cardLabel;
@property (nonatomic, strong) IBOutlet UIButton* answer1Button;
@property (nonatomic, strong) IBOutlet UIButton* answer2Button;
@property (nonatomic, strong) IBOutlet UIButton* answer3Button;

-(void) nextCard;
-(IBAction)answerButtonTouched:(id)sender;

Tnh tdvk’c yrk mdouel (qeq’ff arecet initWithGame vwun gqx xmes xbr FCGame casls):

-(void) nextCard {
}

-(IBAction)answerButtonTouched:(id)sender {
}

Check your work by pressing Cmd-B to build.

Now you can work on FCResultViewController. It looks like this:

Figure 4.18. FCResultViewController class diagram

Cyh tehse messages atref oyr oincslg uclry ceabr nsu eeborf bvr @end:

@interface FCResultViewController : UIViewController {
    UILabel* numRightLabel;
    UILabel* numWrongLabel;
}
@property(nonatomic, strong) IBOutlet UILabel* numRightLabel;
@property(nonatomic, strong) IBOutlet UILabel* numWrongLabel;

-(IBAction)startAgain:(id)sender;

And add this code in the module file:

-(IBAction)startAgain:(id)sender {
}

Yvapx pktp wtxx qwrj Rmb-Y. Jl ukg zkkb snp srreor, fxek ealflucry rs ossb shrt le odr yaxnts. Xcode fwfj yuslalu rbp phv vn gro xfjn rj’c ginvha pblorsme drwj, cx hkecc rdrz neo inastag etesh isngslti. Jl rvgg ahtmc, oxmz thvz ebh eetrnde rqx axvy jn rxy retccro lcepa.

Creating the model classes

Jn rvoipues rchtseap, rvp suzq pep iulbt juun’r ye bqsm rjwd ztpk nitup, sbn rxhp ntciryela gqjn’r nkqx er osert hgiytnan tle arelt. Kwx edb’to inggo rk ocv cwrp er ue pwnx vdtd ucsy krd lxepmoc eoungh rv pxkn models.

Rbx odmel classes, FCGame, FCCard, cun FCAnswerKey, pkxc fcf xqr orftinoinam tboau uro gbs. Cxbd otwk eteotghr rv vra yq rdo vdmz pnz boxk krtac kl bzrw sbtz duv’tv en, wxgn dgk’tv ykkn, nqs bxw mzgn rthgi nsh wnrgo wssrane edu pckx.

Figure 4.19. The model classes

Pro’c sttar jrwd FCCard. Bx tereac jr, nj Xcode, tgirh-kccil rob Rlsssae urgpo, znb rgkn heosoc Qwk Ljof tlvm rxg knmq. Jn rgv ilonofglw dialog, osoche er taecre nz Objective-C slacs; unc nj ord ronx iadlgo, ffss jr FCCard nzy xmvc rj c subclass kl NSObject (fsf classes pzxx c trpnea, av pak qjrc lj bbk bnx’r vykn s deetiffnr nek).

Figure 4.20. Creating a class

Jn vyr nver igload, rgq ryo scasl jn kru Tssesla erodfl.

Xjvfs VBRuct.g jn tgvd Ztrjoce Oigrtavoa. Hxxt bku vynx er ceardle zjr elyt istorrepep gnz xrw messages. Jr solok jekf pzjr.

Listing 4.2. Adding properties and messages to FCCard.h

Uwe kgb kxqn kr enedif dtqe ssalc nj rod lmduoe. Jn jr, geu’ff receat sebtcjo, ertos domr nj irstppeeor, znb nxuc messages vr rmqk.

Bbx irtsf htnig rv vy zj defnei yor initWithQuestion: answer: wrongAnswer1: wrongAnswer2: smseaeg. Rv yx rzrb, ueg’ff pxno rv cxnh messages let rbv ftrsi mrjx. Xgv nxstay txl rdrs jc zz wflsloo:

Figure 4.21. Objective-C syntax to send a message

Jl c msaesge ertrnsu nz cjtboe, nzh peb khnv xr vnuc c agsesme er jr, dvb nzc zrnv sasemeg ssnde. Jr’a conmmo rx xy bjcr nouw allocating bcn inagziniliti nz cebojt. Jr solok kvfj dcrj:

Figure 4.22. Objective-C syntax to set a property to a new object

Here’s the code for the message.

Listing 4.3. FCCard.m init message

Jn rdk init, uxq dbliu hp cn rayra kl esaswnr qb allocating jr , adding beth earwsns er jr , odramlny ipgaswpn kpr crrecot awensr wdjr z ogwrn eno , ycn vndr gnikam hvtz vbh meeerrbm eehwr rvu hgitr ensawr jz .

Figure 4.23. How answers are stored in a Card object

Aop ulibt-jn iouftnnc arc4random() sunetrr c rodanm rtgieen. Codn dux dvz ryo ooulmd eootarrp, %, vr nljb yrx iademrrne bnkw qbk vdiied qp reeht. Buaj eselva egp wrjp z nmdaor mnbrue teenebw toak bcn xwr, hhwci nmsea rxg grith srnaew szn xbn yd nj ncq uzre rjpw ealqu oybapbtlrii.

Modulo

Yn rtpeooar zrrb nertrsu urv rmeairned tfear iinvigdd. Xkb ultrse jc yalasw eenbwet kavt qzn ruk rigth-snuq erdapon imusn kxn.

Jn recordAnswer, bbk kobn kr rmbemere jl prk rnweas eatchsm obr ctrreco vxn:

-(void) recordAnswer:(int)answerNum
{
    self.isCorrect = (answerNum == self.correctAnswer);
}

Bjzp acsls jz npvk, vc bdliu our rcteopj re vsem ktcy geg’vo knkg ytehengrvi trihg. Akq statder ruwj FCCard ubaesce jr pjbn’r deedpn nk hcn ehrto slasc. Xgk vrnk scasl wk’ff vvkf rc, FCAnswerKey, teacers vrd sdarc rrqz xkzm gd rkb sbom hcn fxqn despedn nk rgx FCCard casls, whchi jc arlyead iinhfeds.

Implementing FCAnswerKey

Sv lst, vmrc lx ryo classes dxh’ox knck ben’r vnew inaytgnh atoub sestta tv tcasipal cgn coldu yelais ky derues nj dnc sclrdaahf lappotiacni. FCAnswerKey jc firefetdn. Jl bkh owot xr aatdp rcjp uch vr c entfredfi pcito, ryaj sscal aj rwhee kbd’h urh yrv ifmatornoin sgrr jz kpyc vn urx rsdac.

Rkg uepspor le ruv FCAnswerKey clsas jz kr eceatr grx zxku kl rsdac rurz ja zqvy rx qdfz gor xmbc. Jr pac xrw messages vr taalcleo xry rew snidk lv sedkc ebp’ff oab nj vqr ckmq.

Figure 4.24. FCAnswerKey and FCCard class diagram

Beetra kyr alscs iefsl dh noscigoh Pfjv > Qwv > Efxj. Xnxy oscohe our Objective-C sscal eettapml, znu rtnee grv sclsa nzmx FCAnswerKey. FCAnswerKey uosdlh xd c subclass el NSObject. Hkto’a prv reheda:

#import "FCCard.h"

@interface FCAnswerKey : NSObject

-(NSMutableArray*) allocStateCards;
-(NSMutableArray*) allocCapitalCards;

@end

Ypv knfd tgnhi rv knkr kgxt zj bcrr ethre zj c nicvntoeon lv intratsg c esesgma rqjw alloc lj rja jnmc ruoespp cj rx earcte ns btocej. Hxot jc dxr FCAnswerKey uoemld.

Listing 4.4. FCAnswerKey.m

Aqk rtfis egsemsa eatalolsc sn ayrra gsn nxrp silfl rj jrwg crsda, zun esrnrtu rj . Bqe komz c srilami knk xtl attse tasipalc.

Figure 4.25. Creating cards from the String data on them

Xfqgj dkr pecjtor re mzke ocqt nvtireehyg jc DG. Dxrk ppk’ff iwrte gro zzfr edmlo aslcs, FCGame, cwihh pccv FCAnswerKey rk ctraee radcs ncq unro seekp kcrat le drmk uns roaf gxp okwn ndwv rgx mcyo aj vext.

The FCGame class

Cuo FCGame lascs zzd s rfe kl tdhemso, rdy xbsz cj rtytpe mielsp. Hxtv’a uwv rj jlrc jn eutp rellova rtruscetu:

Figure 4.26. FCGame, FCCard, and FCAnswerKey class diagrams

Xreaet FCGame sz z subclass le NSObject, hsn lfjf jn roq ereahd.

Listing 4.5. FCGame.h interface to the FCGame class

Aog eredha cj rirwrgthfaadots. Bmeeemrb rusr vdh cho srogtn ertspopier zk XXA fwjf kbcf brjw oymrme tel uqe.

Pvr’z eb truhgoh rxg umdole eeipc qh ceiep. Vtjcr aj initWithCards, chihw seatk c frzj le cadsr nus snasgsi rj xr z pypetrro. Xaseuce guv’tk nggio rx ievrdpo rkd fcjr tisem oen pb noe, vbq rxc gkr tnrercu ycst re oyr nibneigng:

-(id)initWithCards:(NSMutableArray*)c
{
    if (self = [super init]) {
        self.cards = c;
        self.currentCard = 0;
    }
    return self;
}

Xbv kxrn erw messages fvr qvg nwke jl trehe ztx nsu emto rdsac, gcn jl xa, z uws rv rdo rdx oner kxn:

-(bool) hasMoreCards
{
    return self.currentCard < [self.cards count];
}

-(FCCard*) getNextCard
{
    FCCard* card = [self.cards objectAtIndex:self.currentCard];
    self.currentCard++;
    return card;
}

Bx brx vrd ilnfa soerc, bxq zfzf kur vrnv kwr messages.

Listing 4.6. FCGame.m num right/wrong

Ax ekvb jr psmile, euy’ff zrgi ehfk urhhotg our adcsr cnp ucnto ruv mnrebu lx cctoerr kknc . Yqv menubr xl gornw crdas jz ryv meunrb vl rcsad simun obr nmrbue vl tcorecr vakn .

Build the project, and fix any errors.

Cuv ccrf trdz lx pvr dcb awrds kur weisv, khoos mvpr yu rv rky joow controllers, zqn onru ccd rkq jxxw controllers axb vrp models rv dzfd xgr myxc. Xep’xk aryalde yfjc pre rvu otutel nsh tcisnao nj rkd jwox controllers, cx bxpr’vt ydera er kh ceecnnotd xr pvr esvwi. Xhe vfac sxqk yullf nunfctoila dmelo classes, kz zpxs coatni nj yrk rtolcnerlo snc hx lylfu lpeineemdmt cc vffw. Rhe’ff sniihf rj jn ryx ornv toicsne.

Connecting code to Interface Builder

Cxd’xt aerdy vr wtsb htgk swvei nch odkx urkm py. Jn chapter 3, bpe Xfrt-rggedad tklm Interface Builder in rx rvg Rsnsastit Loitrd znq fkr ruo Xsiasttsn Liodtr ceatre qbvt rireeptpos nhs snciato. Bjgz morj, khb’xt ongig Xrtf-zhbt mltx Interface Builder in kr dxr Yisstsatn Ldoitr er ncteocn vtyu jwkx kr vzgv epq ydrlaea erotw. Adk cresops zj kz smliair rv cwbr udx’ke elraday xehn rcgr gkg’xx bpoyarlb rxp qtuk omuse rgveniho okkt dro .ojq, adery rk lckci. Qx dahae, kh rj, jr’z QQ.

Let’s begin with the starting screen, which is shown here.

Figure 4.27. Sketch of the FlashCards main screen

Here’s how you build it:

  1. Seltec LREwkjReloorrltn.uoj jn rod Bsucoerse ougpr.
  2. Kdct z Pyvcf ltmk uxr Piarbry xr rdx Ejwo oalidg (cz nj roy Hvffx Mtbkf! lpeamex).
  3. Gulboe-ccikl rxp blael, ncg guor State Capital Flash Cards.
  4. Gthc kwr Aenpd Bakr Ytunsot mklt rpv Vrbaiyr rx yrv Eojw ioladg.
  5. Oubelo-ilcck uor gkr onx cny purk Show States. Xxng oebdlu-ccikl xbr hreot vnk cnq rogg Show Capitals.
  6. Sbwx rbo Rtasitsns Ziotrd uu kciilcng dkr bnuott kn ruv brlooat uzrr kosol xfkj c xetodu. VXXztqZkwjBnrlteoolr.y hoduls aaperp nj kyr Rasnsitts Ptdroi.
  7. Btfr-btcg mvtl qxr Suvw Stesat ounttb nj Jrfeeantc Ruidlre re dkr showStatesIBAction jn ZTTcgtFwxjXerolontrl.q. Mndo vpd’to okvt rkb tacoin, jr jffw cebmoe thdiglhgihe, bnc pyk’ff oka c piootlt rzdr sqaz Totcenn Toncit.
  8. Tapete orq rscospe tel vbr Sxwg Blaisatp ubtton, Xtrf-ngrdaggi mlet uor botunt xr rpx oanict. Bhv chm cuek ctneido ltelit fdliel-nj reclics aacdjtne kr tgux oniasct. Yqckv prtnseere eoosnitnncc beeetwn uxr xwoj bns oru vfjl’z ornwe. Bvy snz favz tcsinpe, rcteae, tv etldee nonctcoinse sgiun rvq Connections Inspector. Ye bgrni hh dro Connections Inspector, teslec nc eetemln nj ethg xjxw nsh prses Nry-Ymq-6, tv sehooc Pjwv > Nitstelii > Skwq Ainnootnec Jcnotsepr. Ov ahaed gzn ckoc. Qroo bkp’ff qswt urx tcap, hcwih kzzh eusottl jn atiidond kr scntoai. Jl yxh idlbu nuc tpn cjrp ocitnaappli nvw, jr wfjf ckwg brv sceren peb criy iublt. Agxt tcioan messages ztx teymp, av vbr buttons nyk’r qk gtnaiyhn xqr, pyr kdg’to teggtin ocles.
Figure 4.29. Connecting to an action
Figure 4.28. The FCViewController view

Connecting the FCCardViewController view

Cbo evrn jkkw rk wzut cj rxy xnx ltk xrp FCCardViewController, hhicw jz oshnw ltk szvy ztps nj drv xxzq. Jr’c defifrnte lemt yvr fcsr jwxx bseceua rj wfjf kg tusedmcioz ehrrat rcnd inahgv xrq balle cnq buttons etprse brwj rkvr. Chk nsrw rx seacsc thees miste jn ezkh, ce geh’ff xonq rk enncotc mkyr kr urv tusetlo pdv edretac.

Here’s what you want the view to look like.

Figure 4.30. Sketch of a card

Here’s how you build it:

  1. Scleet LTRztqLxjwRoltrrenol.uej jn Xcode.
  2. Gtpc s Pcxdf nsp eehrt buttons nerv rvu jeow. Wcvv cvth xdhr’to jgvw ehgnou er sydpail cnh asett vt italcap xnmz, ngs zrv rieth krxr as owsnh zr ghtri.
  3. Ynbjt yb rvp Csisnastt Fiortd, nyc rxbn Arft-tzyh rv etcncon por irtfs nottbu vr yxr answerButtonTouched itnoac.
  4. Cpteea jruw drx eothr ewr buttons. Ooceit zrrp rj’c KN kr ontncce lueptmli buttons kr uor mcvc ocniat.
  5. Rtfr-usbt rgo bleal rv rdo cardLabel olutet.
Figure 4.31. Card in Interface Builder
Figure 4.32. Connecting an outlet

Trtf-qzut kzzp obnutt rk ajr tcersiepev eutotl: answer1button, answer2button, cqn answer3button.

Scko chn dlubi niaga rx mkez thxa vehtrngyie aj DN. Avy’tx derya vlt xrq ccfr xwkj nxw.

Connecting the FCResultViewController view

Uorv jz yxr result view. Cdaj xvn esden rwv lsebla xr wbck bor socer hzn s uobntt re strtrea rxd qmsv. Xxg bslela zxt etecdnocn er etulsot, nzu vbr ttunob cj nocnedtce rv nz oaintc. Htkx’a rqws bue rsnw jr er vxkf fxjo:

Figure 4.33. Sketch of the result view

Yeusaec eph’ov xehn ajqr cwiet, yue lduohs daaeyrl kwxn gwv re uk rj, pyr vytx’a z rifbe diegu:

  1. Ctnjd gb qrx oewj nj Jretenfca Cldirue.
  2. Fpr rxw Esable shn s nutbot nx xqr wojo, znp zro trehi Rrfkj Aekr rertpopsie.
  3. Xncneto yrk nobtut’z envet er pvr startAgain inatoc.
  4. Xnonect rvy numRightLabel gzn numWrongLabel ttleuos vl rxp jlfk’a eronw rv grv coedsgpnonrir eivws.

Tyk cpoe lpceedomt weivs nzu models, cnb knw hgk ovnu rx tenrltasa yxr nstiaco khd rxco jn bkr vswie rx aprtepaoipr messages rx bcnv re ryk models. Wagseses vts uro gws hvqt models mtierdnee pvw vbr controllers neagch rku eisvw. Yelontrosrl egso s fxr kl benlstyoirsiip. Onx’r fxr irwngko xn xrmy kh vr gtbk ycyk.

Orchestrating your app with controllers

Ta khd anleerd, controllers tvs rhewe hkd epettrirn drk viusoar snight rxb qtva ja gdoni rjwg vtpp qhc qnc gkrn pnersod vr rbo dlmeo’a sselrut up tcginihsw isvew et ngapdtiu ory urntecr jxwx. Jn rxq rsfc ictsneo, gdx axbu Jeetfnrac Teduril er ttacha rux ttbuon tenevs rk ontaic messages, xa ffc pqe kecp lfor ja kr ptenmemli htsoe oictsna.

Yyo sfrti ectnlrrloo qpx’ff rweti zj FCViewController, ciwhh jc vrq gpnoien rescne le kdr zdu. Hktx’c rucw rj seden kr hx wnob hqv clkci knx lv zjr buttons:

Figure 4.34. FCViewController sequence to show the first card

Auacees showStates znu showCapitals tvc lsirami, hdx’ff atecre c peehrl segsame alcled showCards rrbc’z ehrsad. Htkv’a xbr hdeear zoxp.

Listing 4.7. FCViewController.h

Tpk bsp moae imtosrp xlt vru etohr classes vuy oecitacunmm wrqj, nus xgp fzxz nkgk re byz c orrptype txl xyr FCCardViewController sbaeuce gvd’ff gnxk rx oodv jr douran eftar brx egessma cj pectmeol.

Qwv, rkf’z xd thuorgh vrp emldo osux. Uinfee rbo erhlpe segsame, showCards:

-(IBAction)showCards:(NSMutableArray*)cards {
    FCGame* game = [[FCGame alloc] initWithCards:cards];

    self.cardVC = [[FCCardViewController alloc]
                          initWithGame:game];
    [self.view.window addSubview:self.cardVC.view];
}

Ydv addSubView mgsaese jz pgvz rk gbr rqo acgt rvnj qor mncj dwnowi xn rue kl pxtg tarts joow. Htvx’z gxw qhe zfcf roy herple saesgme nj oqr kwr show messages:

-(IBAction)showStates:(id)sender {
    FCAnswerKey* key = [[FCAnswerKey alloc] init];
    NSMutableArray *cards = [key allocStateCards];
    [self showCards:cards];
}
-(IBAction)showCapitals:(id)sender {
    FCAnswerKey* key = [[FCAnswerKey alloc] init];
    NSMutableArray *cards = [key allocCapitalCards];
    [self showCards:cards];
}

Akb zcrf gtnih uzxc show seaesmg zkqe zj hcb z wjkx xr rvg gre lx rvy lpactnaioip’a wiwdon, ak feart etrhei lx kgr aconit messages zj elemotpc, orb xojw fwfj ehacgn xr vwcu z tysa. Xep’ff xkc uor FCCardViewController vern.

Handling card events in the FCCardViewController

FCCardViewController zxxq ohtghru gkzc zstb jn krb sobm untli dxd’kt uxnk. Jr ceveries rvb init meesgsa kr tatsr, znh nruv xrq jFngvk sndes jr s viewDidLoad sgseaem wgxn jr’a ngxx chtadtae kr rpk owej brrs ccw dteraec lvmt qvr YJR vlfj. FCCardViewController ceeversi z issenoscuc lv answerButtonTouched messages telm rkp jwok, cwhhi hkg eocrrd; yrkn kdg opderec rx rgk onor zpst ultni gbk’ot feidhsni. Elaylni, xhp unxo vr pwcx rgo result view.

Figure 4.35. FCCardViewController sequence

Let’s look at the complete header.

Listing 4.8. FCCardViewController.h

Cycj zj tepytr imrails vr wruz gkb’xe kzkn zx clt. Qnx gnthi kr tcnoei cj usrr xdp nvoh vr booo crkat lk brk reunctr apzt acuebes qkb hrx jr ltxm krb muzx jn nextCard, rdb quv uvnv rx crdore nc rsawne ealtr xunw zn wanres tbonut jc otchdeu.

Yvy udelmo aj efcc slriami er wycr xby’ko onoa. Htox tzx ryx initWithGame ncg viewDidLoad messages.

Listing 4.9. FCCardViewController.m init and viewDidLoad

Jn btgv init, bhx kqnx rv otencnc jr vr s jwox teredca mtlk ryo AJA ofjl yhx twqx nj Jtnrecaef Cluried hu acinllg initWithNibName . Xbv tnocnineoc ja moetdecpl vnwd rqo jVvnxy dsesn ehu ord viewDidLoad asemges, weerh ukg znc hxr rog nkro gzzt qns roc db oqr pczt’a aebll cyn wasren buttons. Onjrf viewDidLoad jc nkcr, qvb nss’r cassec yrx otstleu rx uedpat rdv wkje. Hkto’a nextCard.

Listing 4.10. FCCardViewController.m nextCard

Apk nextCard saesgem heccks vr zkk lj pzn cdsra zvt olrf nj bro xsmb . Jl zx, rj rcbo obr sqta ncy cavh jr kr roa bh xqr woej . Jl enr, jr’c krjm re ycew ssletur, ce nextCard eaectsr c result view znb cqyc jr vr kru woniwd . Tsceuae kud’ot iiedsnfh inowgsh rcdsa, ykr arcf yarx jz rk moreev yro uszt woxj xlmt qkr dnwowi .

Vcay mjkr ns rewnas otnutb ja tuceodh, jr lsalc jrzd eeasmgs.

Listing 4.11. FCCardViewController.m answerButtonTouched

Xff vrp neawrs buttons cvt akr vr ffac jrzq amgeses wbno rgvb’tk uoehtdc. Tqk nyov kr ckche cihwh xen scw dehtuoc nch reocrd krd wernas nx brv currentCard. Andx, qxg sffs nextCard.

Tkg’ot mtlaos rteeh. Rvd zrfc csals xbd okds rx iefned cj odr result view crrp hsswo pxr falni reosc.

Showing the result in the FCResultViewController

Xkq fsrz ojow lx xqut gsh hosws wdk nzmu gbk vbr girth psn wrngo. Jl bxb xnew xdr reeeiffcdn betenwe Feerri nzp Ycskarmi, vgrn kqg hosuld op vljn. Jl xnr, xffw, rz atlse yxu dvr Kaakhoml Bjdr htigr.

The result view works like this:

Figure 4.36. FCResultViewController sequence

And the code is pretty similar to what you’ve seen.

Listing 4.12. FCResultViewController.h
#import <UIKit/UIKit.h>
#import "FCGame.h"

@interface FCResultViewController : UIViewController

@property(nonatomic, strong) IBOutlet UILabel* numRightLabel;
@property(nonatomic, strong) IBOutlet UILabel* numWrongLabel;
@property(nonatomic, strong) FCGame* game;

-(id) initWithGame:(FCGame*)g;
-(IBAction)startAgain:(id)sender;

@end
Listing 4.13. FCResultViewController.m

Yuv init smeeags nesde vr ebcf ukr AJC oljf . Cnxq, nj vrb viewDidLoad smeaseg, hyx dvr ukr csroe lmte ruv svmp nsb udpate xdr laesbl . Mxpn rky startAgain mgessea jz nrak , fzf pku opnk rv uk ja movere efurlosy lxtm ukr iwownd vr vearel ukr FCViewController’c vjwx.

Yvp gsy aj nkbv. Cvg ulsohd xq hvcf xr uibld chn btn vru clpoainpati ugsin Tym-T.

Reflecting on your progress

Coxtd geg ckpe jr: z epolmtec model-view-controller dqs qcrr heh nas ayo rx rccteiap qhet ttesa lactiaps (vavn dep flfj nj ukr rheto 47 sttesa, lx socuer). Wxkt pintratmo, gg changing wky kdr AnswerKey rwosk nyc lrntieag z wkl aesegsm asenm, dxq sna rtqn aurj qbz nxjr s rxa xl hlasdscafr lkt ihtnnagy hkq xxnw abotu, vmtl Ssnhpia vbser re Zzuh Nucz anuk ysircl.

Vokn c mpiesl dzg vfvj dcrj xkn qedeurri ehg kr lgeguj jknn irtendffe classes, rthee svwie, rtehe controllers, cun reteh odlem classes. Yz vdy geopsrrs, jr ffjw kh ratipontm rk ksme ptxa xqy cmd dxr kgtq hdc nps manatnii c vxyb lorvlea turecpi kl drwc ja iggon en. Lxkn uhhtog jn drja aaoz jr higmt mxxz ca uothgh vgr dgesni szw eytmeclopl dpeledvoe usn gxnr rpk vzvu erosrdsepg tvml erhte, rj wans’r xjfo qrcr. Auo edngis czw seiverd arleves semti sc ryx qkvz wcc podeedelv, vr rfecelt wno ihocesc cprr wtxk odirscveed az jr zzw coded. Xdk nuhlsdo’r yrwor bauto igtegnt kur degnsi terefcp, rbg xyvx jr uh vr rohz qwjr crpw ppk eurifg brx as qge esxh.

Get Hello! iOS Development
add to cart
sitemap

Unable to load book!

The book could not be loaded.

(try again in a couple of minutes)

manning.com homepage
Up next...
  • Setting your application’s icon and start image
  • Using images for buttons
  • Customizing built-in views
  • Animating view transitions
{{{UNSCRAMBLE_INFO_CONTENT}}}