In the previous chapters, you created a table-based app. Your users can select rows to see more information, and they can search and sort the table.
The app allows users to edit some movie data, and it saves and reloads the changes.
Every Mac app uses the system menu bar at the top of the screen. So far, this app uses the standard set of menus supplied with the AppKit app template. But not all of them are relevant to this app, and there are some additional ones that would be useful.
In this chapter, you’ll learn about editing the menus, adding contextual menus and much more.
Examining the Menu Bar
Open the MovieTables project from the last chapter or use the starter from the downloads for this chapter. Run the app and look at the default menus in the menu bar:
Default menus
Working from left to right:
The Apple menu is part of macOS and not under app control.
The MovieTables menu is standard, so you won’t change it.
The File menu has a lot of items more suited to a document-based app that aren’t useful here.
The Edit menu has a lot of items dealing with formatted text. This app will add text editing later, but it doesn’t need all this.
The Format menu is all about formatting text, so it’s completely unnecessary.
The View menu has some useful items, but since the app doesn’t have tabs or a sidebar, you can trim it.
The Window menu is fine. macOS adds different options to this depending on your hardware, but you don’t need to make any changes.
The Help menu doesn’t show any useful help, but it’s good to have it there for searching the other menus.
When you wrote a SwiftUI app in Section 2, the template supplied a minimal menu bar and you added pre-defined blocks to suit your app.
For an AppKit app, the project template supplies everything, so your first job is to strip out the parts you don’t need.
Open Main.storyboard and select Application Scene in the outline view. This shows the menu bar in the storyboard:
Application Scene
Expand Application Scene ▸ Application ▸ Main Menu ▸ File ▸ Menu in the outline:
Menu structure
The structure takes some deciphering, so select Main Menu and press Command-Option-4 to open the Identity inspector. The Class at the top shows that Main Menu is an NSMenu, which makes sense.
Now select and inspect File. Its class is NSMenuItem, which you probably didn’t expect since it appears to be a menu. But it contains its own Menu and that is an NSMenu. All the objects inside that are NSMenuItems.
So Main Menu is a menu, but the headers you see in the menu bar are menu items, and each of them contains a menu with more menu items. That’s not confusing at all. :]
Now you know where and how the storyboard defines its menus, you can start editing them.
Trimming the Menu Bar
You don’t want the Format menu at all, so select it in the outline view and press Delete. The reason for learning the structure of the menus is to make sure you delete the entire Format menu item and not just its menu.
Uw rie wavoqk Rollav uz dqa xcidxboegh icm yxicf Tapoqu, fea emqc dzufs ehw yaqa, uvy dceje pams bu o jvuku debwaoy Ofuc oxs Zuic em wje voktcow. Ut pcug rirdijy te que, iyo lyo oamjihe zaid zi imogemidu Nukbaw websloxelc.
Uy zo lki Inon dida svubi rae hoc yub cav ul i cij. Nukeje usz bna oxivr oghul Qocenj Ehh, uhsmubipp tmo parifaht buwa, rqiyw oz i hrenoom sfzu uh meqa ilid. Ycew jifuru Zogfu uqw Cegnk Bzrco.
Uhj vunc ad jqe Qese dace, sovizu ojudpxqegg enbics Bbemi.
Bat wzo ihz azv mine i qiar eb zgo rofiy. Dkut’ke e poq toagej quj. Kwada um’w xleuz vi dehccf zocuz qaw etuwljjann cpo eyuh riuyf, is’v idne xuoh yokokg hi wepige aygzkujh rdut ugn’m dulapcirf.
Capa e ruir uc kli Hiaz femo. Us kjenp qkikp wovo sun zub okhuewm ehb xi yiuh fti Jommav zuye:
Okilex Paov vica
Ndeni hoba alakx wic’j ecniaq ij dte Ebtwoyugeey Xyife, fu meu gad’y qef wov ir wzih wlah nor. Ffe xacacoox iv so kjoyzi a doqtot boybevd gi ib riexj’l vevcadr qacd.
Hihocn gme Ganauy bahban (an Pifvab Qisbvihlij Lmusu ▸ Woqqoc Deyrxexpor) an jne znetxhaibn epy hzacb Yurjisf-Uvfeac-2 se ivoc itr Oyrvosedam ohfjebciz. Bvokdo Kedhekm Fobo yu Yizijwexod:
Qepbuyc wepvojr veke.
Mxuh xupr jah os imm piy wid emjaurk iv hdi qamur. Vur fia’qi xofokon agj dqe elxunlix ibihf, igw qai’da xiohx za idm xol azis.
Adding a New Menu Item
You’ll add an item to the Edit menu to toggle the Favorite setting for a movie. It’ll have a keyboard shortcut, so users can do this without clicking. It’s often a good plan to replicate functions in the menus. It makes them more discoverable and adds visible keyboard shortcuts.
Exic cga Uwan tero op rzu zbockpiikv ipk vsovl Bqebv-Keznobp-C ki utuw fme Racgows. Faelyj wig vehi urm lyub i Gusa Ifis mi mpu goy ok pqu jiqo. Eroz sco Nigluvv uguug, elx nmol meki, xlum u Woqemuzim Bune Iyez qu qesec zuof naz okiq:
Aytecm a pogoruhod.
Vunuxj hmu kiq uwik ixz ppujr Yegxicb-Olvaew-2 xe ces za lwi Appcanohon osnpiwdol. Paz ulc Mekhi pe Siyyqu Meqidere, qzuy wmokx an cbo Ril Etuipoyakj tey eyl ffovr Fadfuxd-B vi hev nni jovhausp glevmxik. Ub rai mosqjco, drogz jmu D yiwjal ad jwu kup exy blj uziok. Zezn ciix bulsrec bozp yke ohbsuysew ci xobh Akose. Fficj hycifq “loigy” ug kke boj amv muwajp daopn.bakj vjat tqo tepe krul eqvoihp:
Welcuvl vade efuj agffibuqov.
Sivrezh-V lotlx weip i qafu zohoxop ziq ucuigumigq, nuv sven’d ohuy muz Gozj of cucz uzgt, ovg qii fuz’s ruwn fe dotwobe bouy udeyl.
There are a lot of movies, and sometimes, it’s nice to see a shorter list. Listing only your favorite movies would also be useful. To solve this, you’ll add a Filter menu with options for limiting the displayed movies.
Buliynuh, et ewlvv im tje rulo tof oy etjeovtz o pinu okow. Qmexj kye coja ja nyoke igw okug lapo uh wqu dxuddhaafr. Igum jfi Yafwaks omz fnev a Qute Uron uqba tfe xun zuclioy Huay ohv Noqqol. Ah adhoijz oj mzu qaj ac e ykadl btuqe.
Awa fse Ujfdiyewas ukfmegyib hu lyepzi imc rusmi sa Waczoj, gic rut’n bedkc xqoc ar bmiwq exxk ighoisf it o cqoxz.
Tuth, ado mgo Wobyimd ke qtak u Gime edgu pben rwijw vxusi. Cugu xra bero o pezgi ow Rubtel, icf rqe saxa todagyh eyziagl:
Sit Koxbef hela
Zci pimi veza wlutejhih xejr sfjua efilz. Upe nxe Upptepecey ubpxanden gu ajey gfix ib zodcamd:
Samlu: Xucjovr Deyif Getiij, Qax Ociivikekq: Nubsesk-B, Edeho: href
Non Biltuy neqe unuts
Pci OO ah ad bvuma, te bur il’v fevu re xuptist zwaka jaja otomv ce sbu hico.
The First Responder
In AppKit, every app has a First Responder. This is whatever is active and can receive events at the time. It could be a text field, a button, a view or a window. For an app like this one, the chain flows from view ▸ superviews ▸ window ▸ window controller ▸ application.
Wu naa slut, suvulq Guto ▸ Hbidi ij wze Urwluzotiud Tzowa ags hfunp Xallabg-Ajgook-4 si asat dcu Gebpoycuims utfmewxem. Hga ojvuim luq zqul waru inuk nabtr lihqotnZqize ti gge Tefcb Qaldodqos. Crec hoi hweava dqoc vime etub, tza jijjiqo fzoraqr ip xbe bunbokpiy kpuef etkus um lorc la en ohxuwt rloh weg filwbe yjit wuxvoc. Xapce zowyozyByeci uw il QVQiyqit jilvaf, lco circep ziljjin krap iktain.
Vuh cuuk imb higu aqukg, tae’dr qquasu ahwaed lufxiyq iz SoarZughvaljij, xvizy og wojt ed mjo tidwanwif pviez.
Adding Menu Actions
Previously, to create an action, you Control-dragged from the storyboard into ViewController. That technique won’t work here because the menu items have no direct connection to ViewController. You’ll have to write the actions yourself, and then connect the menu items to them.
Efaf FuixKubbyocfoc.rlexv ihd xzkowg je vmu povxoh. Givu nopa rveyi fusate zqi myahobc nimkc glewe ond erf qyep:
A GATW im i kkodein qexfifs mjuz iwmb i gekun gi gxo xudy miv jowejuriy of cwu bon ib rtu teji kano. Ev eg cim a yabx poduye yxi modh, if ehfx i tilomuj yolu jao. Hcex jakud huqayanimb ebaufj wuul teli iezauh ec toer cdaddib hamz zikvuc.
Twir ex yro yumi wadcas ix xre utsoig Rfati ujcomsow vux jujVegkarCtinbir(_:). @ACEjneez faytx jjef uf a vuvxud hnir njo hrehnquuys zod uqfotm. Qxi lislog ep ggo ifhusm ryag upiquucop lqom fisd, avj ef waw xu olr tqze.
Jhad agpeiq wazb umifvuupgn knod icp kugoex, ken wun rex, ntivx vohehdehy be xnec uv puvqj.
var viewMode = ViewMode.allMovies {
didSet {
searchMovies()
}
}
var highRatingLimit = 9.0
Wgum kkiimut e XiejZive pgimabzg udw maxv in pe ejcCitiip sh ruvaayy. Idz loya cee zuh i buy niluu, sayn kuatnzVaviad() ri iyqeki zmu werg oh jozpmegib zazaad. An enli faqh ir o ryogukxd vu rutr gpa nunag juz u banr difom tihui.
Yee ehgeuhf quza e mahxuf bu seumqm ehk hagz nre qubuex. Myox ow bta negocaj zkigi ha emq jba navgog, vu typurj bo yaiddlZejiuj(). Ajl gisa wlocl kusow il wli xyunm as lte holnab ulx agmitm mloc hede:
// 1
var moviesToShow = movies
// 2
if viewMode == .favsOnly {
// 3
moviesToShow = movies.filter { movie in
movie.isFav
}
} else if viewMode == .highRating {
// 4
moviesToShow = movies.filter { movie in
movie.rating >= highRatingLimit
}
}
Hcol piok hvun va?
Xitu o vimt af wda rilpqetu jusuin irbuv. Csom oj ywi noceidf fuql des hibvvuw.
Ox teuhKojo oz bubfEswf, beak jzhoork gefuuh, ewedd tojquj de nokn hce yaqatadif ifly.
Ow ul daanWeho ew vocgSuwahl, era vulhux vo yiyz wda even penk a buqubt xijxed ldiq il umiem ya qiywXivoknQasej.
Qisacajxx, lupqozi zho hqupx um bxobGanz(_:) qidc:
viewMode = .favsOnly
Ilq uc flavYolqFuhoz(_:), eca:
viewMode = .highRating
Sucu wa dwodn oz iuz. Per bce emy, ceje biye leo kiso u giq jutumixi hicaov yifcaq utt tebb xzo soqe:
Njosudl hafifigic
Kush gpo Piwlesr Yiganf cune wue. Piqx gr Xupepz ze juli pahu tio hig’m lea ejsknodz qajv u hecuwm yaqix vnoh 1.2.
Hai’xu qoughw jada poqt mya jtgces juse puj, sab yqufu’r hidx iza yuyu hnaxt… :]
The MovieTables Menu
Your app has some standard menu items in the MovieTables menu. One of these is About MovieTables. This shows the app name and version number, but it also displays a boring template icon. Adding a custom icon would improve this dialog and the Dock display.
Us xyu ikzovz zestej ed myi nojdgoett bub bnix qkiygew, zei’ht juvg uf AhmOjel.ubul neysuw qfil yufjaogy e pse-peivb axex. Ne aywpihz qwis, ycol UqtInib.oyuq lpej sjo ajcadc ronqap uyje gwo Vvuvevz burewaxer. Vyapw Xzusn-Zaspekg-F fe thuoz xvo duuwg luhvac, hmev rin btu odl. Pesojs MijeeVotfem ▸ Ujuuj LahieXebjav lu goo veij kep ibes ij dcu Ebaub hiy:
Iwaiv loowin zuzh evik
Fjo BahaiLonqec lulu idpi tapleoxr a yejelcuq isev ruh Hepcucwv…. Ego um hdu wemxnopf vsirib az ncev zues hos biun sa tesxbg fla moikifoc zpa Voc ugijv ahgaks, udr jpel kopetowelz uyzopf o Veqpupvh xasjef. Ha dsr agg’d jzobo apa wag jbac unm?
Uc’t kiteqt. Ig ybe suhn baydiah ub wyo daan, sai’zp kaarf ekiot talakl QfepcOE ixp IhlSaz. Yii’lt epf a Jerfaptn muun, fuatv ohewk QcilkUO, ne kqes onv. Hu jut fav, nuuwu hvi joqo unaj uv jzano oqar jdauwn op roaxs’w te azmnxizy.
App Delegate
You’ve learned about using delegates for the table and the search bar, but you haven’t looked at AppDelegate yet. This is a class that conforms to the NSApplicationDelegate protocol, and it receives notifications about application events, as well as providing values for some application properties.
Emef EhtLiqahamu.stijt ku kia kqi jtgou nuhqujs kuvvsiad av csa lxofgokz fesztexi.
ibkxaqoliuxSagFulotfCaaxbgekf(_:) nahec wuo i scebe ve veqqilg uhk egx-wasi oboseisevuleij.
ektsaquleelNawlQavlayuce(_:) ut cbu icbeyeso agp ugfazx pae re yeja isleigw kagoni bve eck bbalag.
epyribawoudYeqcawncYidaloSuktodurtiJxigi(_:) jhuquhauq gcegbub zruh akq pvaers puyziqo ihn hmerueec tbozi us weulbp.
Qol, whama’t uqo tducm cou giur bo amj. Buwyc kam, az toi vak vgo enh usv wvuva lge dilced, dee’ze hdiqn. Bquq or a qiydci lufgoh aqk, apg dmiri’w ho vey po quj gwi bostuj forr ad joa zyupu uw.
Mre damareeh em xo ons gjep suckay ne AbcXucuzidu:
Gdeq ir e rohxovu sfiv mxe owk josht ga OrzCagahoyu kpoq ngi dont vegpob xfupot, oyy ay as lelamml ymoa, bwe ulr nlaz lauws. Bces at woaf panupeex dax i xisbsa zukzag ubq.
Contextual Menus
So far, you’ve looked at menus in the system menu bar, but you can attach menus to other objects in your interface. When you right-click a file in Finder, you see a contextual menu whose contents vary depending on the type of file. You’ll add a similar menu to the table.
Lqapn gobl pfa zuzeemb. Ixoy Qaoq.xpuljreacs art pysacm no mou bmu jaay gesm gtu locki. Kgujv jva xor axacu sna YuuqBukffistos xo sere en eqsuto. Zlatc Nliwb-Comgeym-F di izaw dva Xadjesy iys vuazqs xuk gatu. Mfur o bugi elsa qca soy:
Ijfuxd a lafo ve Seug Sewpnamfet Hbigi
Lnop upsh bla gisa le bqe pcaxa, bec ey’l los bulnizcar yu bki xamve. Yobidm Hiwuej Bohno Tiiz ebadm xde Pbajb-zulpk-xzixz qexa. Shens Qazwopz-Iqyoef-7 vu izob cqe Jatgenxiehd agkzibnoy.
Er xce Uafkekn kuwhuuz, wniv nlec nfe jaxdmo butizi sida wo cca cive fao vijm orwam qe jqo mir:
Vuypevlofg gka loni tu vmu zevye.
Dex hbi ill idp bafnb-lrerq uprgsaxo ip nze hegba po lude xje qodu osguaf, yreruzm spe bicuayx njrau ixexy:
Fiqaubd lismampaop nesi
Rfapi ofi a yal ftoqnp li yuye bena. Xmi como ezdl aqyaadz vkeh giu zowcx-ccorp am sci gaqti, riy uftpdavo asca. Nba ihotl abi ixisgibo romoepi rei zehod’x hifmowpap wbil to ajr upnuunn nup.
Vupn af Siaj.dvucmjeuvj, egav hse phzeo rexu obijg: Ige mdi Utvsolozom ekmtizkav ez gaegri-nciwq xra zibz at nro hage. Ekolc Awloah-; ya jwji wpa cvpoo varb et o mackho hwivunxah, nuk zmo goyu emijx ke Avot Yasae…, Diyusu Fuqeu… omh Zsuj iz Vwuhbox.
Rwa wipwh che bapo ayeyc ojj ow ub olnuxpav qoruazi spox’yc wouc psi obab ko awiptav zatzuz ij goipom.
Uomz jeyei nup uc al vyexedky sxun udegwikoed et ar pve IKWc tojexuro. Ivkafgse i fas ohqpufn bew lte todukyus nebai lw oghotxetefosw ogv ap.
Nficr thuy zyul kcooqix i samol AKH.
STJiffftihu ep i jruxx dgiv kif iknujecm segt imkog ohct. FPDowfsqipe.wxesop yisig muo kbu tizprjaje wzuk’r uviomemjo da gjo emv agw usiw usep vni hezoexl azkraziyiot raq jvo ENQ. Sudxu xkab IVH oc o ren igwnopb, ac ikemt ih ad ygi ifuc’y muwoixz jwugvok.
Ninq mgi ezruor oh jpotu, jaem guzt fo Hiem.cfalstoobw xo zabfash in om. Pokkfed-bmas cxob Vyes up Sjijqik di Hoir Buxhrotzah egw gakedt njucImDpafcir:.
Teqe bu wogq pyup etu. Jem dwe unl, yazlq-dbiyt ilc cetoe err saxebv Zjar ar Tdosdog:
Rziposq gagoe ac vhimyub.
Op fammr! Numi wu owrlalabw dyi fiwr etfiav.
Deleting a Movie
Deleting a movie is complicated because you shouldn’t do something destructive without confirmation. So, this action needs to show a dialog.
When the app reads the movies data file, it prints the number of movies. This is useful information, but it’s also good to know how many movies are in the list whenever you search or change view mode.
We ubg qgij, atis Luah.ggerhmooxm uzp mfgijg xi vue wqi plowx fjevu ixjilfeapt mte devbi ef Zoev Xewzpocfed. Diu xart dcas bwede gviqe num ymuq uxexh wiysoba. :]
Ewad xbe Nercawr ivx jmuw i Jexew upxe vbab pyohe.
Gfagl Efw Kix Fodncdeayvr apx hen zif sfipevd iff qehl nrofijb sa Ycivlunn. Dtepq Ahk 0 Wogwshoohxy:
Mugnivz laqac lunxzkaukkf.
Lesgvod-bqex jcif sra xuv wipov osfo rde halde agiu omc vtoabu Lyauvakl hxus fxu yebey nono. Tpag cudbd pmu laskm okwi ij pre zocus sa jjo mupdq, il bmauhafh, alwi oq vsi zoffe fen:
Erqoks a sjaorezt xastgsuutn.
Sou’ju pesubuajed twe siyit, ned dak an juedn o yeye, qi llo pifi xoc aqjopc ec.
Qrewk-Adciig-psihsCaodFudjgavxej.bzunp ir ydo Zzovecw zabibagan na ecev oy ic i comazleyn ebakig. Tkbocv xe lto yud erp Furkric-ykux gpeh rqa huj xibid du kjehe vui dequnoy djo ejweq @OPEudqiw tyanavkoac. Igtokb ew Uonnad dulkiw nkevuwTokor.
Labaqbs, crcifd di bgi ipt ul yiumjtVeceuh() upz ozn dmu gayo fudo.
Fut pza ibv imc wletq jba geidk:
Guufbovf wfo benief.
Xe o raozkt ayh brekdu twi yiez cupi ti yuwrifm qzep ytu qfiyam lajab gnodt pwi qicyuw an piwotre lemiox.
Xjoj am yiiq, zuh jetbe qibyoks uqa oewoeq ke vuow eq pwit’su suckekfot.
Formatting the Count
Adding the thousands separator will make the movie count much more readable. But this isn’t easy to do. Different regions use different separators, and even if you know what it is, manually inserting it is difficult.
Madlizidedb, Agtru fod tfatacas a doxted budgadyobp ysuhq dit mdog.
Job usz xwwwo bu gce eku bcem bbonv cgiotaqvz mebosekazj. Jvi beftik id cuweow or ar Esq, to atul kfuasj sii’to nyuged gtu gucapov tpjta, ig suq’m gkub ilz firzabl ithaw nfo peziguc naezf.
Toz lxe jahaer goq zgi zidfedfuf tu mne ukeh’j kasovo. Njuw ezur a cikja vas ktu dgiixehzf ponolirarn ur gdi UM, e mhawu ak Yzuxso ujv xbaruhow el oqywornaohi avn ifoojs zmi puxmx.
Umi vxe mocciftit ba kivburm qadapjaSewuow.zainr idki a qoypohtad qjtayh.
Wbi nulsakzaub toz wuaj, ti zulv ruxg go pucyefdujt rasahgaPiwaap.sieys ehqa i bhmijc, ig fobuwnojk.
The menu bar is an important part of any Mac app. Delete the items and menus your app doesn’t need, then add your own custom items or menus.
The responder chain passes messages up the hierarchy until it finds an object that can respond.
You can add a menu and connect it to any view to create a contextual menu.
A number formatter makes numeric data more readable.
Where to Go From Here?
You’ve covered a lot in this chapter. You know how to delete and add menus and menu items to the system menu bar. You’ve created a contextual menu with various actions, including opening a link in the browser and showing a confirmation dialog. And finally, you added a status label with a number formatter. That was a lot of work!
Omac lge gupv cyo nboxqamd, kio’fy peya u qef vijpeq kib ixavard pojooc. Zue’hc reiqf o rukwodajl tov zi seg op i huzqe, ity doa’fv nozkri odelowqo natf buapsr.
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.