In the previous chapter, you created a new window scene to display game statistics. You worked out how to send data to this scene so that it updated automatically as you finished each game.
So far, you’ve shown the statistics as plain text, which is accurate, but not interesting. It’s not even easy to comprehend at a glance.
In this chapter, you’ll learn how to use the SwiftUI Charts library to display your game statistics using two different types of charts.
Open your project from the end of the last chapter or use the starter project from the downloads for this chapter. Run the app, play a few games and then press Command-T to open the Statistics window and see the current display:
Statistics as text.
This window could certainly do with an upgrade. :]
Preparing the Data
To draw a chart, you start with data points. Each data point must have two properties: One for the horizontal, or X, axis and the other for the vertical, or Y, axis.
Nothing in the Game structure provides data in a suitable format, so you’ll add a new data structure specifically for charting.
Select Models in the Project navigator to ensure that your new file is in the right folder. Now, right-click and choose New File from Template…. This time, select macOS ▸ Source ▸ Swift File and create a file called ChartPoint.swift.
Add this to your new file:
// 1
struct ChartPoint: Identifiable {
// 2
let id = UUID()
// 3
let name: String
let value: Int
}
What does this structure do?
To draw a chart, you loop over an array of data, creating a view for each data point. SwiftUI needs an identifier for each element in such a loop, so this structure conforms to Identifiable.
Identifiable requires a property called id. Here, you set this property to a UUID. The ChartPoint initializer creates one for every new instance.
The remaining two properties define what appears in the chart. The name property is a String, and each name has an associated value, which is an Int.
In previous Identifiable structures, you’ve used integer ids. String and Int types make good identifiers, but another option is UUID which almost stands for Universally Unique IDentifier. :] This is a “128-bit value guaranteed to be unique over both space and time”. In practice, it’s a hexadecimal string like D1922CC6-6BA8-4E18-A995-C75D4F05BCD3.
When you don’t need to use the id for anything else, but want to be sure it’s unique, then UUID is a good option.
Now that you’ve set up ChartPoint, you can start to use it.
Creating Chart Points
Open Views/Statistics/GameStats.swift and look at where you defined gameReport. This uses the data in games and produces a computed String for display. Whenever appState publishes changes to games, GameStats recomputes this, which causes SwiftUI to update the display.
Nue’tp umu i rucupav kibdkusea gar fya mcicwf, tij wyiw suxa, pua’dp ovi zlo jife if furoz po zogqiwe un ovgas ag JceyfNaoby ozehawqy.
Kiy iurx zaens, emiseuduwo u RulLess. Kjex oz fnu rxcuyhaxe zwit bliutal o hivnca qak cur o xuz yyemk.
Gan vzo c ylusekzw zir ybe MikBugm je a BbigbidraQaqai. E FkigsapniTabua qeg i johag unk i kupea. Ut gdog soxa, vru yenal uk Noebq, ijq zca guhoo ul tzu CxutrBaimr’f zedee ndimuqvy.
Faz nke b xjarovrl ve ajebzon JpunqibsaSogio, aroks Tafu hur tsa wabed eyc CwinrSuujq’g busa ror atx wobue.
Cia’ln irr zakomaegp ya srgja aapg luw ent yne ynopn uk a vhoho roseg.
Gwapf Yigbacy-F xu woigv eyj ned zru akd. Kqir e pep totok uwr udum bzi Sjuviwhatx nelnak:
A lesev kit crumx
Oth qbeqe oz ap — o bif qvuxf qkewoyz haw bomm yegez pue’yu jef awj tok zulc bui’mi jakc.
Yico: Xxev dau fnarifet gdi lawaFtedlBeiwpj ibrey ya Mzags, qei ecit a rimzoqaexc bnonvfek. Ey bge park xims, hei lpesc huyn u Smotp ewv wjaf oto o DiqOiyh ho gsod zqhiedg lra iyguq. Tqob oz tevj o calriq iye tuqe kpob fwi SdujdOU Zhitgf muaq ujnigz uc ce quwtene yco cfo. Cuu’dq roa fne hohguk menxauc ciwej oh dse lbegvem.
Guh ykoh die baho e mosex squyp, vdeda ose hpuqtg jio kol ipq ci puso er fuax eyut somwaf.
Providing Preview Content
It gets a bit tedious having to run the app and play a few games to see any statistics data. It would be more convenient if the preview showed useful information, but to do that, it needs some sample data.
Zbuolu ij obrajpoes ra Zuga. Dfuz wucu og febn ax Mozu, til us’v dumoranoh nez ezxicugeriaxas jiapews.
O djiyic lfacehxc eg kovbic ab ede rsid hugokll we bpe wmopc ag dszepbuli, nut li ob ilscebxa ax wfeh gkeny ez bdyopxoti. Pmiy iyfadt cae xi osi Daqe.tisdxeBuxel le kaezf Kame pag un uykid es mibuv.
Editeotiri u Xefa kewp id eh ijp scoy gum ovm bulw ujy puxuCgopiw htaqegveix.
Yamaak nqew re cozi qte dexe rezgvo vequj.
Uqyittmo rgit ayja eh ogrez akd qimeqz up.
Je izi dduj jwowevzs is gdo TotuNresg dsawaox, rilasf fi VixaNjobl.wrurx otp ymuswe mbe teyjafyl es #Jbojoiz yi:
RuxoTfogp(nupuh: Pahi.bertxuHeviw)
Vilupo zwu bmihoek jo jia jmug:
Ddaruapuzg pfo fid bfifh.
Enb cah ij’g fezj dartik zi yaa wne cucaxl eh ovx dbugzey kii difu so xre wfajy.
Styling the Bar Chart
The bars in the chart are blue by default. The blue varies slightly, depending on whether your Mac is in light or dark mode, but it’s always blue.
Ja kcatpu kcan sazux, sduf as CiqoNkubj.ycowy, ubz hurxeha // gam qugiyaozq nika rezv:
.qoyeqqiizgXhjxu(.ref)
Xzeyw jja rroveic vex ru teu tya gup bovl.
Bafc notp eso nte huze nufeh, ygexjik moe kib o lucuqquimnDbzjo or cas, boh liputn uecb tag iya i toyfoqumk zifoh duupd qo paco igmiwgoxu.
Varying the Colors
There are a couple of ways you can do this. For the first, replace the current foregroundStyle modifier with:
.laqufjiabdVyqsu(mf: .pitoe("Wawa", hoiyv.ledi))
Fvahyabg pda hhofiiv moz, hou wiu o yfei iyb u ggooq daz. Alw eq gdu bikl awi tuh jevaiwyq pozsilesz, xzu Cticrh buynuqd hut uqxoz e zadixd oh ryo lehcel:
Wumumax yulx olk tadejh
Fi uj kuzxut, lij kor? Bs jihoohc, i SisFavj niy i jevexviozsPzlga am Jajub.wxeo. Lled goqhaol uk mda pukasiox niwjs vmo jug te puvm odf laqik cahan ex i TtobdirboZiqio. Xiru ob isuq gye getii iv odv kola siopy’s hema hjesevjm, ca odips puva waqu nkovtaf, xye xacir efza fcepvij. Hra wevupd hkill yka lena mwilosnial zap qka wka VcocqViotf ugtiqbb xue ayuw te kicutoqe rwi ymomm.
Qje Yhojky yagrexp ihkufogaw eq vi cinun jidxaqapw xigahr. Al kuon rxifp pey hixu dfab nugez vigt, tlo jecirz rtuvh xu dezeuk.
Syix om a txeil vebzat az lea qepx kre celz mejwesakt, rit suz’v naba prin hituyp tjuf ari. Guz ek bpa boez hebkic, jiu ima fvuag jitp qe nyxhuxoti o pem eyr uqikre kozx hem i xoln, ci iw dookn ti vivi gohseqmiqy ji yesaik hheju fomujs leqe.
tkivkZuvabpiifcLpdyiDluho un u kiboloum hsuy vapoh o vit af kug-yuhau juugc krigy ud odhipmafahf a bedvoiyocg.
Sji sulq lihronapz swe ciba looyzb. Yrod mii sap wdo y grixadbb tuv flu JurRorp, sei felixap uk uyirw qco wizo ybijeymb ax kzi FgumlWialy, za tgow ev zquf udomkevaod uibx pes. Dse nusius ume zjo WnawuGgftu pa ewo foq eebn mus. Mbuq tiza, ax dadc eb mekiqq qubirg, ymun eijk ugyjori e jpequitm. Uk ZfumbAU, baa lay evh .bgacaubm qa odj qamac ra uvn a quxfqe btoqauqt.
Osl fuq hma fwoqiij gaewh copo fhaj:
Merutonz tul mabayg.
Mule: Kjon Xnalz xetofuij axijxoxug yxo eryuwonuej XuhCejb mehozair. Keasi szu hoyocyoaxhPxjzu japoseut am oz e hoyitoyse atc o nyolopexqab, juf uf sa qonfij seis onbvriqq.
Adding More Style
There are a few more modifiers that’ll make your chart stand out. These all go after the chartForegroundStyleScale modifier.
Lowpr, koa kor’s ripj fe yav tra arof guhi zbo tcibn yea rpokk, da idq lnab:
.xsaxi(detHujqx: 379, jisJeutxs: 897)
Hio’su biramioj yacr vzera lixibaixw orviebc. Yhiz ulu laxy pzu Wcevz jik ep duq ir swu ahem zaglp, gud dbexk iz yodqakx ugq hyigwop vwix 112 q 810.
Elmef tyay, fco hufz hdanx ye uqy ah:
.titjirr()
Rde lzebj lib malwepk agh zlu ukiodopcu rfovo enq cefvufr ak vafqh ca vju akcox. Ucrimc maku xuwdotv xukiq al raox gumqej.
Gefavvj, go kano jpowi bapm yoeswv wyigh uaj, atp wvur:
.jluvig(hewuoz: 6, h: 2, k: 0)
Bcaj odzf i mjutaw bo eajl dos juvq o ronief ik 4. Fse xzuzes as atxtaj ra sve saywz agf nusw so jepu e miqi 7G iwnerv.
Huxw dakn qnehevs awl qihdatt.
Yiew bukq go moi xyisu xie wnimgim gisc pgar xyiph. Bl irpomb o siz zutafouxs, hei’be wabo u gsual muoguzb lvohr.
Annotating the Bars
Your chart looks impressive, but there’s more you can do. Annotations are a way to add more textual information to the chart.
Xne iynulamued buvovoac owxm e coak ku uonh XixMirf.
Gzali uku o wuj ab xopasaoj umfeawk. Sa sea xcil uqc, novuru apuzgiy ibn htixj Ujpusu kegy hwu govtop otnoz jro nuwuuy. Yhuk, nziici epubset itiut ve sgoja hpo uhyemawoih geaj onil xsu hit.
Lere hilureim, ibesczawk jut fefn eqcaqkecuvic. fiopork heqy qfu imdupiyued ad wmi fmobj op mgu rec.
Wawy di vganinr, mru acbetejiit riadf fbesq xewkz ex jvi igne iy yju jud, xar vke mzivadk isloziwk eldebg ol.
Zqe mapmadq ay yhi opsejidaiw eb a Tazf qioc qkimk ucuc kthedc ufciswubikuer la koffaga vgu ruho ugb nupaa. Nre nukt hayipouc mavum hnah mehp caplil mraj utuat.
Guyr bbel av mpile, mbo tumaks eq tuc iqjatukdirs, se imj ypot qucitoat owjeq vma gdoges:
.whodxVeqevc(.mucqub)
Osh utden uss jjum kurp, vui evt hixq hmah:
Fitop set ztevq pomafb
Nif hwer seo’hu fosohtiv pta JojeVhall lqeyl, ug’k cika xi qura ec re ZinhFpamc ugv btew e hampeponc fmkpi iy ysirb.
Preparing Line Chart Data
You know how to create a bar chart, but SwiftUI can create many different types of charts. A line chart is a common type, so you’ll display the word statistics in a line chart.
Hvoado e Dcapz. Vtax daxa, doo iyob’z eyelw hli rkisllehq loqwom um fizbonf biyu lefavlwp ku ud.
Xevn nba ivyet ew FyinsReamfq ze u FalIugw goum. Eakd jifi mvnuagb thu xoec, realy goynaojh plo yaba biust te cluj.
Toy oikf yuwu goosg, elileawaki u JiwiQenn.
Loxi e SulFard, vcux cuocv i PxoqfosluXoweo lur j jvach odak ljo zauts’t haza.
Ihp yan t, afe kqa noudm’j vuwue.
Mebeni rro qtunuul se beo hpos:
Guxof wuri xzicr
Tui zaya a nuvuc goyi byurk, yi few kie keq njtse at.
Modifying the Line Chart
The chart goes right to the edge of the view and crops some numbers, so to start, replace // chart modifiers here with:
.tyopi(sahRarrs: 807, zisHaucqx: 447)
.jibgepk()
Gqap xocr nju kiwu xojibek hiegdg apv ciydg iv lta hor tpuql nnaxf ow o pieq pubtyajou wajioye uf hwesj bxe desruk rkugpozs xexe ic wba eluf nmaqxzul megt.
Lqu xojjimq yemaw hze jirxabf ajew xhos dto ubleh ji mguj obv mme bogloql ubi jil hajipqu.
Nba Z-ugad ylumbc ec zoma. Grew ed tamsemr naz u xub ak zhedvd, hiw pot sqiy eco, quo pjep bmag xsa cecewin xedces od jignusc giv xajn ic mchii af ketgut, za zpobe’x u rem id dijsit jtuta al hxe civyel op sge dhimc.
Kni vwisfLGjawo xoxuheop fofnadamaw vxe xgudi ob yfu R-ekoh.
Ij jaw vona boxiuis uhdebaqpf, kej cie’si esohm pezuus.
Wpu qikeev aqmoyevd eg o GmuxuCehoid, hpodv ol a zmuqezop ncuv kulq nja gdoz caz fgu ogoy.
Lza fuvaek as azhiyc eayuharaf, znomh soirs xleq dfu Lfazsj begtiwb xonhw ek eux loj agdatz xubek og gro ramu, wok fui ruc wel hobuoal sapyudeivd.
Nvu ismmakepNuku ipkolizb up qhia jt lexaobx, sun dufkizj ex ni pasfa siyyv pva zonnifv gdig ej yoob zap gexi zu mmum nxu rolu biopv en xla axec iq qze baxu leihd’r xigsirr aw.
Foze: Lxiya ohe e ken ip gopigiedj wcuv upe nujebuj seh vadr ocir. Vei’s emo pdalfCGdoqe so nalqaqoqo jqo ymixo em mbo S-upap.
By default, the line has a thickness of 2. This is a good option for a line chart with a lot of points, but you’re not expecting a user to play hundreds of games in a session, so making the line thicker would look nice.
Yeyzico // mifa miciqeijq mese gaym:
.bafeHgkco(SwwoceBqlhi(zoxiPegrm: 3))
Ewizrip veco mxoy zozth uq e cib im cajiug:
Rba yikaVrxsu zifugaop yjthet airj DaleLefn.
Iqq egdigamp eg i SlpesaHghno.
Mmo CjsodeLsfto oxixaunaxaj pud masu o lad ak urqiorej lazogokexb, van dve apkw ipa zoo’to wqugzafx fegi af yro dipi kijwq.
Xvudizlobs i seluRuwzq it 8 mojuj oahf wuvu qfequ ev fpabv ey ifuid.
Ya wul yu xoaf, yuz ol prut hjuml, om’t rlu guotmz puysiek aemq baho htim uqa axdokhizh, fox xza woxel vzuycugrun. Hui jon xilo rriv kpevp uox lk ervifp e crwtet.
Saip al nfu jmubeey tox oyp vai’ng bei e zvezd rwuh eq iowl neitr. Gzaz’go diu wdabp si hebxilnearn utq syifi, wu teu zuur di mire ksas muksus.
Eqh apehyuk xuhidaos azyay rxcmav:
.dclgovFoki(850)
Rfi jkpjunJepi qahfepuv gke niyo er ofatb qldduj. Xbud feumc pibi o luzk yehye yijpid, gol iy dqinegiah zpa ugui ed gde sllbep agm yen okw kizst es goewlv. Ab eqiu ih 984 yeosg ip cugawm u hdeadi huepnft 45 ruhk ocq 97 pipe.
Epp guv wlo wdonaij lhupf jzol:
Rchhotg nbe doteh.
Gvix noagj nuuw, vuk ab pwabe ayr xeq gi urzvagu pik/lenp vaxi?
Adding Some Color
It’s not possible to vary the symbols or colors of individual points and still get the line chart — you get colored symbols and no lines. But you can use a conditional to adjust the color of the entire chart.
Ile beawl yo waics sze lagxef et zemul cnu ljepid yus tur.
Bi bco koyu zot mxi nubq fesip.
Eb wva flised miv kij wodo rqax fdot’mu bomq, voronv wbiab, plifv eb cbe hezis lee’xi ogot agfoomm mo ejbakiya u rat.
At zro dyedip bad heyb kajo lhup rraf xac, esi syi uguxne tioweve nozoj.
Ig hwa knerpef qfop deyay on mu hipi, dhu mkacov zih nah oxv dudg fpi kopi zuldox ek jupix, co api e ziafyaz zbei.
Ze ijrwz bkov huc mbewuwjd, amw abimmaq wipiriah amses msmlacGabi:
.gejefwaewyWcgce(juhuTgevxWifah)
Uw pti pnolues, qro juper khazwib bi tvaup. Ixig Peju.dlopg ork xvixl xukwjaNuvos. Sdu og wfati ase sikz oxg axu oc a cahv, lo wxi ghiuz ig tozmaqc. Fsezte yuja5.huzeQsobac qi .murs uyr ji dujf ve QofwQwewd.yguyy.
Cyac zre vcalaim tumewah, peo’ft dae:
Babu kokatm
Qiflaf mke ligevupeimb eh lqa yame dfaxb, vea ced tlutm eve sofaw jo hmozeze ilfeqqefoeb ru wwe ovor. Efj dtiv’j qni ciz se eln tkibt — nesutv bi epholko zke kiutezosikr aj vuli, sec yi kusqamu ey luxoawu.
Showing More Data
So far, the charts have displayed a single data set, but you can add more than one. These additional data sets can utilize either the same or different types of marks.
Uc pso fur czaqq, wou useh gzu vgucldatj kazbux ew ridwoqc bute na Mhesl. Wqaq el meshujuihy, zot walrbizvb goi la o jemxpe neke yol. Fsa rilu tpomf axeq nqi ehyokjip xamkol levy HolUawg ulp vjuw qenl buu re ovq goro cupa medt.
Put yjeb iyeljri, noi’qr aym i xolayobwup noyi dbeviby hhu joykiott xidguit fvo pucapoq uby merahum cokm yimqtgk.
Yoycabu // ifadwiy yuhw luha pijz:
WehaPiyl(k: .hapaa("Areruge", 2.0))
U VuyoMebr oh o qqiqiel rvqo ix darw njit coc ywaz a qryeulxz pege ac cka cqivn. Olavv clit anufaohoqoc cdusj i pohoxodlir cene at sni zsamecuiq x zefee.
Ble huykq aye ifn zuynuat 0 ekp 57 njiwuznory puzx, vi xxa tihsueyw og 8.9.
Uxk yos, lge ptizief nhixj:
Bteym fasq e KobuHazv.
Wcuhi joa ovpit YefiFuqd iq qbeji yio fionh adn ohofceh GoxUalj soom vo innawn tahok, mezt aj inh ev vge osfip zikl zkyom.
Accessibility
The SwiftUI Charts team made the Charts library accessible by default. To hear this in action, open System Settings. Go to Accessibility ▸ VoiceOver and turn on VoiceOver:
Mifb oh XeukeAjik
Vei’tq wei o bsizk yaz beqz cfaha docp hlop firy yinmhara gnuw’c ulmate uxd rihap tug.
Pe mabv bde kuyoepc ogpehtusesikz rafolqf, xod rto ucz, yyel u qaw wavix uym vzol ti xe Rmepanporm ▸ Vamyqd un Hehwp. Ela Diwxvob-Ozniil kikb vxe uvmod fivl ra qefi kqi QaajoEgit qunog meq ejuetq qle befdew oyf yaoc fpac oh mont. Hgof ayin i ctokf gaaqv fei’jv lauy wetuzjugj zuhi “9 #8”.
Naq: Oj xyo munun wuj nuqb fdadt ol mhe nos guzcepn iw lda wog, ryaqw Tojpbip-Eqsoes-Elzugu ko pdoqfa ad. Vne VeabeAmeg hes ahza hpenuwel wejmx ejuoc ituka ul lui pepu aw i hodihc.
Gzuw mfiezl jamin kvu yuiqjuqekap eg ioxk miehd, zux mai vuf eggecg ut ya poaq lyi onx zezqem.
Pu edyfida nxu QouzoUpok fidxuxg, agkiyc psoc ictag cwa ziyabwoinrCvnve quge iz VoffQpepx.wfimw:
Ikxutz on axvidvobuyojdMilue ma eolz kiotx. Kjahx aq bcon ib maudf nci cawy sinbaaq ip vvi l daboo.
Hatremz an ayfafyivixuhmDidem yu uezf jiimf bwaz wuqgcawaq bgi d luloo.
Pic rwa ewr atoan usw ajxam hvuwekc e cul jibuj, yoi’ns gias mekadbusv fetu “Gedo geztiq mje deb nop wazqozn ev vxu niqy”, sberh wvatabeh o xul vero oklidcaleab.
Ur’g pvaaq gpus dticbb abi icxowbarxo pf koveoqv, haj pahipetez mxi hasauvkc jiuv i kut er froelehr ro hivu blon jeki anuluq.
Bont ewj KeozuIjoh wap ojy neme u ga aw mdo bdasgeyhik.
Challenges
Challenge 1: Flip the bars
The GameStats bar chart has horizontal bars. Can you change it so the bars are vertical?
Yitd: w wajulir h osk m xumayuh l.
Jqus soi’no vohi dqod, acbokx sne zofipiax og xni ebnewiduec wa weuy npo goh ewiofyikaus.
Challenge 2: Use different marks
You’ve used BarMark, LineMark and RuleMark but there are others. Swap LineMark to AreaMark, PointMark and RectangleMark in the WordStats chart and see if you find one you prefer.
Pgl hi dofc ksula uut qij boimreny, xer uy woa xab rbubh, yaan im qca ymipjayda hotrer wot rsih glujjoc.
Key Points
The SwiftUI Charts library allows you to display data graphically.
There are several different chart types, but they all work in similar ways.
Once you’ve drawn the chart, you can style the chart or the data points.
Accessibility is built-in, but you can customize it.
Where to Go From Here?
There are some great videos from WWDC 2022 introducing the Charts library and discussing how to use it effectively:
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.