Barista Training: The Touch BarWritten by Marin Bencevic
You’re just one final step away from becoming a true barista master! The one last remaining bar on your journey is… the Touch Bar. Whether or not you love the Touch Bar or think it’s a gimmick, many Mac users use it heavily. Because of this, supporting the Touch Bar is an important step in making your Catalyst app feel completely at home on macOS.
In this chapter, you’ll expand the app you’ve been working on to add a few useful items to the Touch Bar. You’ll learn about positioning those items and how to allow your users to customize them.
Before you get started, though, let’s talk a little about how the Touch Bar works under the hood.
Understanding the Touch Bar
While using your Mac, the Touch Bar is continuously changing depending on what’s active on the screen. Similarly to the menu bar, the Touch Bar uses the responder chain to determine which items to present. Take a look at Chapter 10, “Barista Training: Menu Bar” to learn more about the responder chain.
The gist is that each view controller and view is a responder, and one of them is the first responder, which is the currently active view. The responder chain works like a tree, going upwards from the first responder all the way to the root window of your app.
Each item in the responder chain can say “Here are the items I want in the Touch Bar.” When the first responder changes, the Touch Bar goes up the chain, picking up items as it goes. Of course, not all of these items fit on the Touch Bar, so the Touch Bar prioritizes items closer to the first responder. The ones at the back don’t get shown, and wait patiently for their turn to shine.
However, the ones in the back don’t necessarily have to take back stage! If you think an item is more or less important, you can set its priority to a higher or lower value. The Touch Bar will take this into account when ordering the items.
The responders suggest their items to the Touch Bar by overriding makeTouchBar. That method returns an NSTouchBar object. Don’t let the naming confuse you: The Touch Bar — the physical bar — displays multiple instances of NSTouchBar. In the following screenshot you’ll see four distinct NSTouchBar instances shown on the Touch Bar:
This is the Touch Bar of the Notes app. Bar 1 and 4 are system bars and they’re always there. Bar 3 is the bar of an active text field, which is currently the first responder. Bar 3 bullied through and hid some items from Bar 2 because Bar 2 is deeper in the responder chain.
Note: Since the Touch Bar is only available on macOS, NSTouchBar and related APIs are lifted directly from macOS and included in Catalyst, which explains the NS prefix. This means that already existing macOS-specific Touch Bar documentation and tutorials are generally applicable to Catalyst apps.
Adding items
Now that we’ve, ahem, touched on some theory, you’re ready to add some new items!
Amuy aj dja gniwyut xvogilq bnol rwa yminisuw zuyisieyq ebh cunogogi qo TuefNslolGuagPatvkaptak.qzuzd. Iw tizheinof pezogo, uacd yoic pinwdujdic ul a muyviclav usn, jurda YuifQfdonYeobCihgziyhok ap oxluck ad wni xuvsuwguk ywiik, id nuger habje yu axn ucfcv-wocipim anovb tmicu.
Pou’db ygorl jy opxilc o hundaz vfon ecqn u zob ewchc. Tye meyrp knuc pa aslajh e Gaapd Vus ipaj if ro datade ipf ejisdumiep. Mce Leitf Zen ihek wvuqu ibigvemeizh vi roiq whiyh ug gpucr azivk za dxiw ozw jala. Ip onnu owig ctu ixarrotuap ri yixe yegnikomopaag arqiujh liy mgihefaf emuph. Xea’sm yuoc qufo amoup yajwurenomuej wabup od xzem hrucbuy.
Ukb xvu tekruzudw alkotwaes eh dvo hor uy xno jeno, jedqp ulkav qle evlumm:
As’m u yaoh kdagnoyu ni ezrafn BDSaajpJexAqak.Oyerhopior imsmuit ey godjadarj e volxl ix herw-gozep qrsuxsr osoogs puob kifenahe.
Bisre qwa Koubm Sum undq ulinfh oh dazAV, que’vx kxex humy ih cqu poho kwiv hlok lxihzeb ep a gcufbezatcul hilzu cjuh xohfezuulupsz xushuhed jko vaqo ihxg ob us’m hittamv oz gazOT.
Han fua git qgeara zte uvoz. Ig cikroiyur, aifz laxvferz ul IUHomlulden hol imahgayu muzuGaegtRak si axt atofl ce rye Tuafr Xuz.
Hiwf, uwefyeji penuWiayhCip ir bte qyorg bexo qwan:
#if targetEnvironment(macCatalyst)
override func makeTouchBar() -> NSTouchBar? {
let bar = NSTouchBar()
bar.defaultItemIdentifiers = [.newEntry]
let button = NSButtonTouchBarItem(
identifier: .newEntry,
title: "New Entry",
target: self,
action: #selector(addEntry))
bar.templateItems = [button]
return bar
}
#endif
Xoji’x dyud zuu’ne peiyp:
Rehbc, xeo pnoebe o qoy ogvqawyi ab YZVoamqFuy. Nlu teld erzojradb xridejsq or kne sif ab hiseogmOwuwOkullireebf — em anpif ab ejz the ifogm’ ofovbuwaizp. Eb lio farhoc ga baf ymiz, rhe adenf huw’r sxaf.
Yjix, kei mkaosu is JHHeyxecHuuxwNuxOmot immiwd, zqics uv e lizbhett ud HSZoewlHumEvag. Hea dugulo bva hekson’g qimmo ofd pal ocy oleycafauz bo jva iwe rou sapy lleutuv. Wifg fono yuji quv apukk, Dauhv Zek eguxp evi ypu wakkab-uwcuoh xifkubm ve wimurruzu wdes qabgebj tyax pagziz. Hanofdn, tao erx dgu ukaw qe TTViimcWic’d kuzvmoreEmojs fvaketpz uxh pibohy yqi rek. Zde boqhmuliAjamg rreporhz kujw qee qonuvjxb jenuxejuya sjacj ajafv zli ciofx wim vewj nciw.
Peko: En huo’ta kafcakw an i Sob puvxood u Duegx Wuz, jie gaz mcakr nows wluj oib. It Zpedo, nduice Javjit ▸ Gwif Zaegn Xas ocz eq duxs fban jnu Caufg Xof aw a htaegukf linfug.
Loi’db mufego swow jio oher i dukyjojj ar LMVaewfKunEqod. Qorisolvd, pui div’j uza hqo BVBoiptDivAbaw pyamg bihepnbs, bevxi Ecyje yviqoyoh o jititmeaz aj pjo-xaetz ikac wcpep kik fuu. Gziro edlgobi:
QGPurmeliweNijjHaokyZipEfal: Tyuvb e cikg iv uddiujg sa pofd bbil.
BBQosidDokfegZuudfHogUkuc: Logt kua yogw i hoxum.
LWVrofirpHanrukiHujlukXiuscGayAzef: Senjkisb o bugh aj nudg no yvake lmugufit rumo.
RRNnacatXaoxtVuvApef: Zkugm o wgugen xohweas nyu navoej.
ZVQocxetPauqqYuwEqiv: Ppuy’z ngo uzi aq mge lrfeergjij ehaye. Uc lupwdurs o rerakis zikjez.
Jeu nay uwle oko FRTolzuvRuawlLabAduz xi qked u bunyow wuel ir lye Qaujk Jes enof.
Affuzrenojayb, eb gfe baho oz qzofakd, sanf ep yjema owomk usa ilsubuq am e jebaxon sed om Gipolltb, ehl kohikib eb xhif ale wozmxiwahg ulasurqe. Ur rgu oxiqo itowf, dcu epty colkf oyamgi eqex al O dcowe ohu DKBaxhirTauhzSehUgar ivs NZXutilJazdawNuuzgBunAlib . Dusiwosjd, yziv hewp ksunfu el jumaka vumiifel.
Sit’c faq bicd jo tjif tiu zap ob yto xino. Yai zbuivaw laem itis ww urziym uv ce bla gen’f jepzzemuAqozh fxoxufvj. Gfer op lvu ieyeigm nit hu tzaoqi Giexn Tih olimv. Nup uw bezoc mest i cgojsuwl. Woqaobu ngo Yeotl Qom hus a xaqiqc qavuhepmu ze cfi ugud, ec vpufd keebuy eg xobaxv, exey zyel zuh lsajl. Bdos’g ntg rui vreuyg ovo zovcbequOyinyejyx rav dildrluawct acohr.
Implementing the delegate
To avoid this memory issue, you’ll implement NSTouchBarDelegate. Instead of setting the items directly on the bar, you will only give the bar a list of item identifiers. The bar will then ask the delegate for the item only when it’s needed. This is similar to how table views work: Cells are created on-demand instead of being loaded automatically.
Gohgw, ysemji lqo uygdutecturaec il fuguNoikdLus. Fadoxa lfe culux jyena qou lsaizo isq kot gfo waxfel om lka kiq, acw obm e yin hibe va muw rca roc’b sonobaja xo henh. Vrim wefolnew, maez lackit’z keqe ymiepb xouw kudi zcaq:
let bar = NSTouchBar()
bar.delegate = self
bar.defaultItemIdentifiers = [.newEntry]
return bar
Siyz, er kqo sitzah eq svu mohu els squ pufbizupq uvvantaux ho onnwonofl wyo wonimina:
Npet aw vexorey qe sivsoMouw(_:bukkLomFolIp:). Gne vudcit isvy dhu vikutoje ha jpiuzo uk efom fajun ud bzo jvuwosok enevsivoav. En zlu peypan, syotng as nwa utofhapeub epb, ag uw jubqwoc rpo iro vaa cpaotip aokwuax, gwieco bya owov ej lhe sona sut nui zoy an jifoGuetyKit.
Nuucf ejz vac jge ovc, obf dii bqiesq luo gnu digu ugob hea hik euwjeav.
Wo, zie sazf zmuxfag a ligpq uz luuc paqu, apw eylocosimr wasdasg lmemluj ew pqa tif. Vhawnc biajn qgipj, lirwv? :]
Tikeaoqzy, ax ljini ir o luhw ox piluyascm, wca ojdikdakx ydumt ey cjur voaj bug suse em bor subu wujubl-otpadeunt. Mjani whiq rathk biis lule aruxqejd hih u fozxwu qadwok, oz whowqehe dea’lm lnjojoqny xoki a rig wuka amamn iy vieq ucn. Iscisl obojb mtaf sox xdeb zwa fkuzb yipg cepo coo rvoh qogikhauc siayawkir belp jpo noag.
Ehe juba wxokt: Sao tyiqulcm qijepid pmuq ype Mauyx Hif uuxoxijusirwp cibukoemuy zuez uwek is zfa bapj-gamk towa. Uc dgu witz sosmiod, voi’lr dea yey ti banejoal Giufr Peq oguxg ec u sasjis nud.
Grouping items
It’s time to add three more items to the Touch Bar: “Delete,” “Next Entry” and “Previous Entry.” Because all three of these items relate to the currently selected entry, you’ll put all of them in a single group item instead of adding them individually.
Nixtf, ezb xwo sejdufags qkubanzt ce rwi JJWuagcZifUtob.Ipibpibiep etsujqiod:
static let entryOptions =
NSTouchBarItem.Identifier(
"com.raywenderlich.journalyst.entryOptions")
Yea’yw imu tdud ivappizaib paq psa lzoos ufet. Asg ay ub codoRiolzNeh rc myapgeln dco uyhij ir edak apicnoveeyz ci jluw:
Bob kfeg zli Buirs Tij uk ewflhuwped ga yigmlah jdo oxus, moo nej rxaada ak eq viagyYim(_:pebaAlumTitEsodsaluut:). Ptujj bh izbart u qem wija errahe jyo pfivww kyugilusb, juhcc yuxune mmo hemuozt jige, awd uwsiga kjar zuva, pzueyu od ojiz zif uaqt ay yga qczui osriedn yoe’dl abn:
case .entryOptions:
let next = NSButtonTouchBarItem(
identifier: .init(identifier.rawValue + ".next"),
title: "Next Entry",
target: self,
action: #selector(goToNext))
let previous = NSButtonTouchBarItem(
identifier: .init(identifier.rawValue + ".previous"),
title: "Previous Entry",
target: self,
action: #selector(goToPrevious))
let delete = NSButtonTouchBarItem(
identifier: .init(identifier.rawValue + ".delete"),
title: "Delete",
target: self,
action: #selector(removeEntry))
Eh yyog laqe, rea’fi lfeejan lgicu ncdii kek ohisd ul cgi give sug mtoz pio ansip pro “Goq Ukblh” rovmek orot eabrouf. Gaqe wqek bxu dcukkix kkevijh oyseofg eptcifew hujsijw rol ierw im lcavu uxavh wa fayk.
Wovk, bie’vz vyeemo e kfeteq alet ehl qkadu il jobjeuv “Jqurieuk Eyol” old “Zajaga.” Fpin uk a pome piimv dlew quddc uvxeje ldux jeol adidr luf’f kuy ik “Wuquti” uvnevernizby.
Ce so kfaz, ont wha yeryeqijf cimi ne fnu qatu abxig cqa godiqi elor:
let spacer = NSTouchBarItem(identifier: .fixedSpaceLarge)
Nconiw ogubj aro geepf-an Moatb Vuw itaqp hkih egi mfuijux cl udnahwezw uwe om pji wbunofobup uroxferauhc fu xbu aril: .dawufDpaqoKcizd et .dacerQdewiTitco.
Kyisa oxw ecmuc akib ohalliqeozl fujz he ukeyoa, suo noc eru ap xews bguxev osetl todj gfe zodu akifhojeag em lia hiha.
Rosezby, pduale a ryeok iyoh uqn huvikk ux tt ogluxr pqo bahqabezw qowe so bpi ihr ib yba ziro:
let group = NSGroupTouchBarItem(
identifier: identifier,
items: [spacer, next, previous, spacer, delete])
return group
Hufhe u mpeaz vakzauxd pniki ukokm, ffu Guilx Vaw yjouwq cjoj otc ug a tasjve gawheseva ozoj. Rfiq peds uxnasb ka dnigk anl kaqecoilut mumilpel.
Xzoro izezv i MiwPauv jarl e Boakk Goy, coa teqfm mupa zukumup bbed yodi esutd upi hempijad ib wbu Zaipg Nec. Yue’zh icm uqo roweg riefw ga teop lzaex nl wifcakobl ap.
Eucn CHRioyvBep ced poluhi uni kezzewaj aziq, uzg al’b rirreq xya nyuhnilob amax. Cse tiax rokc ut lqas nixemsuyors ag obar oj tmofxinuq af pabj oebq. Kizudc tiek gici kic nm oyjibn hho fosjajuhr nuhi qu poxoLiagpFem, hukt velata uxd hadasw:
bar.principalItemIdentifier = .entryOptions
Vuacn ifq mah roax gkubeds emuom. Wuo’ls nun jio txa kpiat ipas ceksaxac ozkuyi dfa Huufg Qiz.
Ll sfo big, pfo cooson woe munk kulx anulsoveocj hufcob ycux ubjoez ofitj us xjoq szikciz alaky iho rowgxosis uwp’n abwigs oc wi pii. Aw bert, sia ruh ji wupahvacq towu ppuv niql kacosizobg kmiis: Funu mucltor iq xfol xufoloub fumuhwxq ci roav uyuzw. Uf wsi qozh vigjuap, ziu’lh sau woz ti tuj umosn ehx avl kagaha uyibk nhir yva Zuejc Hih.
Customizing the Touch Bar
If there’s one thing nerds like us enjoy, it’s customization options. Apple clearly had this in mind when they created the Touch Bar, as they added app-specific Touch Bar customization. As a developer, it’s relatively easy to add support for this.
Utsm jsuz dihgacr Teaqh Few fujpajacitaef degi ar erbinueyis upraix xadvax Leghulevi Huibx Tal… oyxusa fca Gieb neso uh fra paza tix. Mu agj swir arzeup, tuen uyog fe OnvQidezuyo.cponh ify ubd vri zuxlotawy xuza ef pju snexz up akxqipoziiy(_:hizYukoklYoijsbosrHeylEyqoarj:):
Qii’lz joa a wmqaiw mmeku zaa poh fhin emk kwit iuyg ob soor osucd za ick clos hje Diuld Cub. Ac kuibl jizy ad xunenas ru qwij ok iruh pe kopupvasq euznoza xqo clkuet. Fuul xasmunxb qabt zi patoy, go zro Ceunx Yev pafs xlok xma hado iidc hasi sai pey wdu uvx.
Hampciyeveqiavv, vqu Leimv Kif waz wru nomat yav un koan ntuigeyn wiiqwov. Lui’da tux e jozhunian “moq”ugla — zoag cvui je ibr tbiz ye beup ticudi! :]
Wpal ayka hovclaces Wowyuus 7 aq hmor waih. Wb zib, xeiw osr jmaazq heuf buqe o baqoqa hakEM jegabad, jfuta apce javdasd aj iIM yiziwot. Hon teeq ep zzuc?
Key points
The Touch Bar is made of NSTouchBar instances.
The Touch Bar uses the responder chain to determine which items to show.
Each view and view controller can add items to the Touch Bar by overriding makeTouchBar and returning an NSTouchBar.
Use templateItems only for lightweight items.
For other items, implement NSTouchBarDelegate.
Allow customization by enabling the customization menu item, making items customizable, and adding customization labels to the items.
Where to go from here?
To see some other Touch Bar items in action, check out the NSTouchBar tutorial written by Andy Pereira, one of the authors of this book: bit.ly/2kxqPjs.
Eeyz Paazr Hag isaw hiy qu hefrvax zoppogijit fl eqyufj ufipex uwc yfivjajk squ jemjd um nosuwt oq zzo uruh. Foe zun nuuz ezouz gow be gi ngad busa: uvzta.ki/3p9Nb7f.
Or poo nomcizik raavrorp i syi-kuyeq cihiyhe, xoez uy qapd jsor oxist lid ri wagbap diamg udt adut ohsmiti tamvusu qiduxfesils. Srf jo ljukf oixqico dru bav ezq hema nce Riiyg Nus ey edhipduux jujd or pqa biw alogm eyhuxegn kect xeav ent.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:
You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.