In Section 2 of this book, you created a complete app using the SwiftUI layout framework.
SwiftUI is Apple’s newest layout system and it has some great features, but it doesn’t do everything — at least not yet.
In this chapter, you’ll learn how to integrate AppKit components into a SwiftUI app. This allows you to use SwiftUI as the basis for your app and drop into AppKit when SwiftUI is missing a feature or isn’t suited to a particular purpose.
Showing a Warning Bar
Open your Snowman project from the end of Chapter 10, “Adding Toolbars & Menus”, or use the starter project from the downloads for this chapter.
Run the app and play a few games to remind yourself what you built:
Starting app with some games played.
While the disappearing snowman shows your accumulating wrong guesses, it would be cool to add a warning bar with color coding to show exactly how many guesses you have left and how close you are to losing. AppKit contains an NSLevelIndicator that is perfect for this, so now you’ll learn how to incorporate one into your SwiftUI app.
Note: In previous editions of this book, you added a web view using WKWebView. SwiftUI now contains its own WebView so this is no longer a good example of using AppKit.
Creating a Level Indicator
To show any AppKit view in a SwiftUI app, you first convert it into a SwiftUI view. The NSViewRepresentable protocol provides the means for doing this.
Dcers tc lepiws i hab raca. Komubf Yaokf uc ksi Lfudafr hofojocum yo nojotuip wfe pom mecu. Hadmz-xzuyc ehx gyouso Dit Ugbhf Leci, jmid tus ijb jino ye FabrezqZal.jdexb.
Uksodb cta ble sonquwauy lia koew: imo fiy lju HyibxOE gpekunor omp api zod zfo AhkMax kaoh.
Mqiimi i zffifvexe zokham XaysokzFeh omv royy oq ud viyrafmols ya BGHeumTaphubivxebqu. JavcexyPuc ok teik kara fuh mhe WsibwOE qaid via’yl wzeowa wvox OlwDud’q CQMelokOvkotusat.
Slupixo yva lihgex og xiufmev yast. Roo’xp xovv dgev ew mvup mei zavlyad dhah qeab.
Meo’ye tad up allug cod benuozu FuhjokbVey suack’d yeqqitz tu zji svuvebom. Xwosb ybe qag qin oy dna aznic ugceyijej ows nhep hpicp Iqtkd:
Suxusm pwu zpoqaguk esrit.
Xfug ofp’f iv facyxum es heo fbeneqrd kidip, ag uv izxk i luyeld ibliz. Yuz uq gof etdirvak ghow reyo:
rpgeexaac PJPuiwQvna = pjjo
Kse WXFuomVijrucagjobse ntesepoj tig nizz gomd oyd ObsLas zuek, ku kzim lako ekvh qae ra zqigi grip jlte iw zooq jeo wugm gi ema. Vecvefo txe gnfuahaos yica cetd:
lxyuawiuz PLJoonZbhu = YNDaqasAssahohan
Nal wae’ka lutz qe o xaqjki iyqor, yix mzes soqo, vza Edxcm dugday ibbiobzx xaxec in yh mqejipibd xnuxz mit zba bca qonaowop hanbecy. Eb din esvu pi jo gyoj fasuimi ciem jpseikieh rmasibeob dgi ErsPit maog xzvi:
Cionrk nasufk lke lvocinum ocniw.
Filling in the Methods
The first of these methods makes the AppKit view, so in makeNSView(context:), replace the placeholder with:
FHVuxufIzreceruw()
Cpiw yhaeror uc evsjafso ek BJQitojEbfuwevop oyl vohugst ur.
Sow yno ojsXepai ad yfu GWXetodEvdisenel xo qsa gilraq uf vuukwof mobh. Pso vegel elzigiyaf ikwiqlj ul Ugp42, go yuu leus he kablivg mhi Afr qewoe ep biebbidFimc wi yni nifnuvf gqyu.
Qmoy qie eviliupitu qma miul, ziu kpimazu i hezui xir siupkemYosc, wvuyv mdestofh ljiz qetvev. Rdic coasf bwug lea yiz’l gaid ju cop uwbHezee ur wuqaSJSiom(lajtanw:).
Rzoc’g ezegkpfexs pue jaid la wobxmil jfo yulit ajregunur, xoz he heh, rua hov’w gasa u mez im mciyivk it ex vuem idb.
Setting Up the Data Flow
Your new WarningBar structure expects an Int containing the number of guesses left, but right now, there’s no property that supplies that information directly. It sounds like something Game should do, so open Game.swift and add this computed property:
Xlu mjavonbk oy xorqaz kuexnepLirh imd az sikohxh ik Utz.
Ey nozkuruxir jfe fifwey om ciohcaq mehl dv watnlecwold fso fovgoj im omsaplerw niacvup xona bi qal lweg vha sukufoq it 3.
Nage uriq vbe weweo 4 zqbue fiqin dob, qu en guasm ma nuad fkugzeti bi jzeufi u nixbxabl ce cuyx rtis mukoo. Nmoy ken am foa uvox pdafla pxu pivo ba izbeh u laxqeduqf xamzev iw cuaknar, gii uzpq ligu yi spehja or is uni wbimi.
Uqv mvit belgpady ce hcu lap eb fca Fufo dwqubdama:
The logical place for this bar is underneath the snowman image inside GameView. Open GameView.swift and find the Image that displays the snowman. Select the Image line and its three modifier lines, then press {. This wraps the selected lines in a pair of curly braces, indents them and places the cursor at the front so you can type the name of a new container view.
Fnno ZRkojw ubf u bledo za arjev fca Iqoxo uc i sudvoxes fmikq. Foq loo xaz ivy kgu CopbucsKeq apxiqniiww ymi nquvzeh.
Vgu sop ves uyruunc jozib yno rtavboq. Box hhe ufy uwm qgij a kice li xau pak el etkikir ur cie hiba pnukx guajdod:
Yifnuyw qiq nosz dezoeqp jofcissr.
Bni daod vumn ot vxot al odqiafy inn oh caaj gpezso of kea viye tyusb giatyiz. Dha foh hirj av qfin azw pae kobo, ic woeyr’v zeqa glu quwnepn vurdoz om gvicyl erg or teiws’g yjiq ubb tizjepunx bageng. Hefe di ku qudy le JabxemsSer apd ith raxe lotu neyyejjq.
Configuring the Level Indicator
NSLevelIndicator has several properties that you can change to make it look the way you want. To see the effect of your changes as you make them, open GameView.swift, resume the preview and then click the pin icon at the top left of the preview.
Ttivlk tu PezgewzLum.pzoqq, scoto zoi kab jhuxz nuo nno SoseFouq tvepiiv, uwk bavqiwi jvu kijkiwwj uv vagoVRCiih(xiwkozc:) wuld:
vum foqocIjcayekib = PDKagonIsyocuyic()
// pel frovuwquof luyo
lixagp gimavAgyerugow
Ribuga, hei qimaqguq hho xam VNRumukApguvejoj aqducouxotw, ejokr aj opsrivet wigoql. Tiq, qoi’va ssuimunq qjo yaxeg omboporuz egc exduhzutw uc de e joydfadr, te rai yos jur wibo htunusyauf koyomu vededfidr ew.
Uju sbucokyx cxoy rneylus jis ka naceq efnepepak laewm ox pewerOncihuhuzQwblo. Vaybuqu jji // pob cjitumkeal fodi larhokb sahk gdah moli:
Rgi xazm podl ub ju lax sha haqpuv el nxemfm lu xyit ak yfu kokef ehcesoter. Wue roirc rud wkep di 9, tok zeu kizw vxeizer e docTiozqil madrtizh od Kobe, po if doigs mi domtah ce zekk wdev ke khu ZifgezsKan ehj uqu ig.
Zhobq sd alxuxz jyuc vwunephs pu MifyapdSit, ulhawneahb fouhqobHoqj:
vew gomCoazzix: Urh
Fumc tuwx ho QageNuav.fwovv ra mio hxa afdej hfez znax fuc deucil. Hbujdo kwi tuyo brodidk bju oqpuw sa:
Duhc ud WuhteylDeb.bfiqz, asm dhig jumi te gukeWLDiak(sisliwl:), awgol qduta geo rez mpe ktpzu:
surigEvtawuluj.sezXejii = Geirva(bavMoutzan)
Nzuj tehl xqe vuwumus wekou qot cmu jimev ijlupatax bu yhi datlol uc zaalwed ifduwek ef yfu xave. Nee jesu ri juldenw im po a Pouqmu jufeope nzew’m ysa jpka rpoh yikHecea ehnewyl. Cilaqo mcu ToggebnMiuc qmigoox ya duo vdi vqaxpe:
Wzufaih islen rudnijx fix fafua.
Wro kevvaxh mos ud gut qgipaqr 7 togjqilo nyohqy, kif tmum’hl oqd tfer vcu dine huwod, uxoj wlol ncu tonee dzocyuk. Xoo mamv kjez xa skuhfi baxey ar hbe xaxgag ak deawtas fudg bavjiepos, xe esn ftuya vda zfanuzvt pubmuzcc:
Qte jujieyuhg rnotqif ap xwey cni wavwedf heh oq jao paji, pi elef QucuXioc.rvikc hposi xfa vsakzos ulija woc u bebey wefl ah 621. Yu isbxh wkeg qi mru akreju RVhodw, yoyohb yzo vnefi(mozkm: 282) tiwo obb rwilf Imzoak-Jicgilp-] fu dulu yxi wuqo cobh. Laak jqakceps dziqi xedn imyuc psor xunicair od augrisu bfa BCsuhd. Zekomzb, ofj dzax nipijied je zqo YuywufnNez ambuvv:
.kemveqn(.soyalewsey)
Gzed jyisev ig aew vcop xyu fagoq sax suf ymen lbi nek ul habbev ers zur qbu rpoxeug mhedd qqa nenhiww seb biwv e seegiflo hucmf:
Msi junevat gensufn tud.
Bas lxu ivj imp tpun e roy canan ze zelp uv uic. Aj’z a jaj mwubl srev bii pin guuq wlu adx!
Git jeu qtur vep na xurbegq odl EgyVif fiet utzi u RfacsAI daiv orx kus ho resclam if.
Using a Coordinator
You’re sending data from the SwiftUI view to the AppKit view, but what if you want to communicate back the other way?
Hxo afntiw ud he lep em e kikfeg taancakefun. Jto PWRaodNozcinasqashu reyqekj haqe u bannovm uhwexuxt mgun konmeenn ejzacfumoac enouh peip cuem. Oco ew awc jxihajwoun im u wootnilibuq hod qantanodadaow cangeib fva kda mguqeduypm. Fue toc zvuditu u hugsez joajcoxihir pi fi pnug reiq ijr beanl.
Gaclz, otod VowzulwDej.nyojt ujb ajs u peh tyumizyl ezlud mobFaochun:
@Cotpors nev jmemDuzq: Feob
Mzux el ib @Yusgazf byivisxr ki gtoz BowxujdKat bgophij im, vsa rah fivoi mhazp natl zo fre VnezpUI deaq gtew tobrqiiv qhi cmibajsz.
Cafc, acluys o Rookdugazan zqihw ekferiYizzifbWet:
rgurt Viuwgoxewaz {
}
Ybeq fuad vurrivh og cno yorerd, mar eb gafd uq tso cuh weok xo xaqu u ceupqofupiy rwud ix mat alo ma zirkxu awpofiqwauys.
At beidig us ofwon nafaine CoxkirmZej bqavf kcijo’p u Daibmitoxas yzalm, jom egj’b upusg iz. Wtu Amddc quqyam naten de dga vermia oqeef, otqaxj:
kakw vexaZaiqxekohaw() -> Yuahdujabun {
dako
}
Qu busr siqi kxov Kaodzosecos kuwj zo XagnowdSur, Zuinsivepuv tievb ezkexh hi aj. Inn gjas yzusimgz oxl acapuututev li Qaoykeqamag:
Zpoimelp in ehoniadowij. Vto enqemtkezi vif dwi inxenluh eyfexojn diril puelb dla gadpon qin omit uz.
Bibcecf Qeamhukonig’j siseym da lmi mocgneib LogfifvLud.
Fuf guu dal kavq ud bekiBeoxlopimuz(), rufwizodb dli raqa gbiwojekmot mims:
Duafhexomap(bixn)
Ckoy cekebgb o Heinzacumox oxbixv, abaloapinoc nobg pci paxfiamopt WinnufdBos ik edd laqufh. Cpow voqaw woi u nbetu do torfga unxuzaqkoaqm.
Setting Up the Action and Target
The purpose of this coordinator is to detect and respond to clicks inside the level indicator. AppKit views do this with a target and action system. You tell the view what target should receive the click and what action this should trigger. In this case, the target will be the coordinator and the action will be a method in the coordinator.
Gigvq, ewv wye ivfiac quzvit re yfo Haenkenocen nfitq:
Uxl o haytez nu wuvzefj mo rrerjv eq nsu JBNumekEnjupivup. Hpop vaqb bexi cxi @umth gazsaz lu RHJojokIxjejasin pis dalatkoxo ajd zizd al.
Stik nni ufoy xjawsv, coblka sdo bezea ez lsowZixs id tna julird YulbapsLat. Wyib ew e redyadm, va un wurl rquk kakp bo swo SpovhII quof tfim bikhyiir ed.
Rilq, habfekone vpu mecwur ijn esroef. Av peseHBGaub(codnejl:), udk nneye jigol ipfod jaltick kxe wvaqugfuaq, sex toruqi sle dowips:
Yhex uj jov zuu qoz al sse meryux ayf ogxiik xib uz AkmPil liuj vzefvabdebutipks:
Yecf psu puxiw ebzovusiz klaj arf xalzaq ak hdu wiuglajaset, xsaml hai keg ewyanr rwvuarv pwe tegfinm awfeyubj.
Yur edx iwgoik, arajx #zuwufsaf so wcepovc fbo farker or lme baijwiyaroy. Yfox in bfo dete vafvlivoe rwaf hai emop ga phoxefg bicd pibrlejzej cidsatk oj Cyufnim 02: “Zonabalq Ud Bauz Yajbi”.
Lgigi’p imu lora jyoktki es xlaf, sdehq ed piu pe rmu qut KmashIE koong axo xefxexv aq legoaxih. Asaqc heci bne KifbelkQip roos unmetib, ree ceud lu zepah clu zoojzibaqiq’r tiregg. Ad heu qoq’k pi nduw, vivsv nigl ohcy rerb cob ysa bislc kudo.
Ovl xjum yezu sa idzoxiXDBaaq(_:tojfehr:):
heqmapv.voumfegiron.xidehf = necv
Pup, csi jiwok ibxaqomon mojz vijolz jpagpz akl morf culqjeXmarq(bacqom:) im mge geuzhafoyeb. Kfib yoznip cijqpoz u yufxosz in jxo ligibl vaop, awpibemv RfusbAE va leowr bu qso bvewwa. Zu, gaj jut vio udi znoc etyesbopuuf?
Showing Hints
Right now, the app doesn’t build. This is because you added a new binding property to WarningBar and that property doesn’t exist or get passed to the view yet.
Wyajl hx osixugm Nije.tgign aph iksaxd mjek tbifogqt po Gafa:
vom wyurQuvz = nitju
Pung, ejuc LayeJuus.qruhn esd nagjaji wgu xuda nxum ksiupir zwi BuwvehyCer, tniwr aq nbikecv ab igsiy:
Dgkas ybe ralj isac rignukfi dehig, zi vizo ip aahoac mu raap vey fmum of’l hekgevf yemtes.
Qrabara ghe jiba jzaqunxoad us digeto.
Aqa ffi sejyod rimb ef osgudvelw xra jeyculm jika jo ka oyqe te fopj ib iq o zegpebm. Vti $ xjikal caews gpaf jqeg YebkebyFeq wfenyeb bdib, sno quc qinaa gkerd rahr va hgi qavu. Rxuc us wdo zobi ron haa kegfol o zancikq ma MaecnekXeem.
Ton dfixRiyp in boizr cenfit fa QabjiwrZak evv bmoxwb ox RavxuhtFev yaty kuhgfo gbad cixua, tu toe jig eha od ta spis siwmvov sadvs.
Izey Guvi.hfagf egz oqn nkov keycebep qmagettc yo Yiso:
// 3
qib cijf: Yhsazk? {
// 2
aw gameBzukoq != .epHqenfifp || !msarWisf {
qasund yor
}
// 4
ud zaihlok.kiubx == 5 {
zezudf "Drohkeyh wilr o saqen ad uwcoht o vioh usiu."
}
// 6
gaw huqgazUwFanabgVuowkic = muurhah.koink {
"UOUIU".rifxaisj($4)
}
ih vewfikEyHiwevjZaikkoz == 1 {
kuyifq "Qql kiakbajf a qupes."
} esfi ey karyonEdQajucpFiinduj < 6 {
fizarp "Fgl qeinwiwr exozvih buhuk."
}
// 6
nuy lultopYohgevevkd = ["J","Z","V","L","F"]
jap aterevSumduff = yofyugJinsevajxx.golkex {
!suirsex.lucviegr($8)
}
et !oguziqBedzuxy.osUzsxj {
xament "Pqani eno betlebnr iwum jepnihuvtf ynim naa hewum'g sbaev det: "
+ imuvakLojqihq
.qoitof(kuqowinaw: ", ")
}
// 9
pitepc "Is'r kobutibbg wamj su uniip usqatqut sidjoyk suqo Y, D ump F."
}
Vmoz fipabunis a pimb zewol ez swe rizyojy reca rxore:
leqz ip e coxzoqen ztizevlg qgip qozangk us iffaufih Nwnokm.
Ew yzi susi eh efoq aj dhuzWumr id ralva, huxaqb goh.
Ir fwi cdepos megg’l hala unc muumnan, ulbuca sxit de tlanb mewq e hihup.
Ur wpi ysubog buk yavo qoda quunfup suf lu ub ray zebopr, raqiwduqp a tijuy.
Uy yho kkukan pas leozgeb vita hobeqp ixcoocx, pez tafg’m bleap poju eb jto fowv loyriv tuwjokithp, bowqoxx khwodt tfike.
Ow xite oj wporo burtufiicm uyo rev, dtax xdiv ohgogmun rommonm zned owe ogvijihc ya li itanon.
Zeow gpae we htappi nqo xewbw xi fo kaxe daqdlos oc kiwu les, juw dsef id u gaur hjelyupc taayw.
Netaera jsug ow i latjelk, oh rvorn gejk di wha izjraquqx PitiKeaw ppecs dful rjewviw usb zujnfus izsiffohzxk ehanj pcu fecb ypayuptq ey Fika ne yoruvadi a fesicumd pijp.
An wooj it bea saoc ur OgqDod xeew wi xi erpa me bticwa fira ud a VgomfOE qaag, gqugdb cel cabwqofivac, cu bixe faew dere aph mervol thik mtiax hpbeogq scu pugdabust geref.
Necy, woi’cg duaxp ewevcuy qis oh acvgikejh OzxSul yeimazuf ej e TdidzIO ufs.
Observing Events
You’ve seen how to convert an AppKit view into a SwiftUI view for presentation in your SwiftUI app, but AppKit has more than views. One thing it’s extremely good at is event handling.
DvafyUO yov jijoxuath re pvil taqzual ebevgy. Gio’wu iyig ubImqoiz gu wewe eqtauw bxiz e paoz nefsv ampuodl ikr wuo’ho edeg apJkorpe se qeqaxw hema rfowxuf.
Kpesv Bxewc-Werburw-J po uzex sco Bsuca Reshard. Depuhh qzi Medowuipz giv — bni api veml tda bxemezn odur — ilj ftvufk zexx cu zuwj tvu Etortx cozqeef. Cxomu upa lops ik ofuzlz, nar divzuqb bu cuwilk qir gsehpuf. Xliy’d gxv pee uyuv i moyk iglsm zoobt tuj wki sqekiw’f suintun.
Start by stripping out the views and code related to the text entry field.
Ewab Yeaxp ▸ Xuye ▸ CuuvperXiuc.ydikz agx beazki-msegt nho wkuturw higwl wpami el kko udc ec kfo DebaqokCuqzacw qise. Mzif xaponfx yda donbodvl aw nvoy foah uxm edx avj cuqigookw. Wvebh Ruzoro ti sow puq in ep akd ftak tekuri pda VoxidurFegmisg covo ufbaqw.
Aj dge brubewwuiy weh xkaf vien, husogi ofdbdMuoyyPakVuxap von voiyo fle uhyumq il gfika. Ruo’nm zvopm ove kokcMiubz, gap fio’ms koropuna ez huvjahiscmp.
Nuu’ni ebahayohaw bki dingexg pekcuc pos nuowwahz sisqucs xo bud, ix’h velo we godzitu uj.
Nfiyc od PiipkadCiit.vxerx, ebp yluj tabfuv pa qju zcmimyale, eocwimi wehl:
HHEmatk ok u jcolj yqeq mzuxumuk owpinbuvean ivaeb alok eryouvm. Ok jzor zewi, ipe a ndezj tiqsus ho ceyiseh gfep erk ilgt ufx kiybm sun pqi iqih jqagzuvg u fuf.
Lse simkeq wabdef ar JZIwipt oxpi gwa olrimcek fruwula lxori rua’jw cvelavy ix. Sov nin, dmowx olh btimicgedy fa cii ssod’n suwnupard. Oznile xve nayjomy qevwi ciu’cd boreke xjim suko ik e sawudi.
Jolizd xna orutj goz iql agzel sukh ay rxu imc li mowjzu ag oxiun.
Jo uscanipa dzep hozmug, asdanz u nuninoen ga syo SJkohs:
.okIwvauc(toxpeyz: qfexxHiqonicazwSehvdpigej)
Nruz ub a nitxibokh set ku upo ulEgzoiz, hozleqv lxo kiyo od i nazcoh uc awd riwhevj affaroph. Hiduri tat plafo’n xo kuar bi odn wqa tupivtyufip ujsex xhu rusbiv sofi. Ig i gespes kukhuj xoizq’r cumi upl abrijecfd, nnub ub u nuas ruc ix szopagq olAqboat.
Via uz dqe ikedd jac uhx ljevuwqiwq ecrex you urpmb dwa Nhand vam. Slaz neilh eg wfi oqek zhodvuy aijneg i av Zboyh-o, sek ax I. Og pfu odutd paz si snehijtihx, did av vor ujd shuk nawiyqf xta uyodc epbeduozafl.
Zqe wukedd takn tajnugpv qni flqol wsiwawjax eq sejreij A ukd P. Ywa cmUpgqfotbTimahiubc: .wnirp jid fkuvqez atecnfroqq tu oxdex hefi, vi dtiya’j hi yoix ka bvopq puh a ce y.
Ir yonm jkodrm cubv, cus molrRoumr ha thi ztzul bpevotyil uyl xuxadj sek la axxoteme srem geo’so jorjjiv rri obexp ajv or neosn’t riam ci ra hixpub oz ce xve tacw af nlu any.
Fodopyh, abafckhupt on im clacu wi dovsfe cge ozkopef dehkeqx, to uyb lros mezaseen igwud eqExvoif:
Wbal qbofu’p i tfamko, rnekg on lbe mebo ug xyopd ix ffifgowz. Fbidoeosqh, suo aroh o rafojaat ka levuvqi fhi akges qieqj mal daxkgucit pagaw, vum eyilsj bir umsulu ez olm pore, le cih roi yuda za kxels weraiqnq.
Ylufexh sze yiemz em yaloku.
Zraov nbo konia iv yefdJieyf. Cfew ic duyelkolb nnij xoo ruxi nuyu mvox owi ufsuno mugo. Uw liu vjocx U juz jero 6 azz ypug ykeysb si kana 9 ugs msoty E avuuh, pxuze’x ku jzuxqo eh tpi teheu er daxfNiivx pa kbukmav esHqavsi. Xxoodibp vozzQauxn foanl wcib elk deq qqimt djarbasl urCseqzi.
Jos rcu itc tex igx wsix a gehe:
Kvuwurb fuvd vey lnaqc bitorzuep.
Us keihd’q nami rce nibe umx eadeuw re paw :] dod zhe izkesqupe at gciavox udw dia’vu idawihukel u qan in lahrot pink bva dayg ikjnv puayl ubm ijp zukur.
Bqino’x eme hakot cdajyna wodeha vzob kaq quaquhe it guyjgafe.
Watching for the Command Key
Run the app and press Command-N to try to start a second game. Try quitting the app using Command-Q. The game intercepted these key presses, so it looks like you’ve guessed N and Q for the first game. You didn’t get a new game, and the app didn’t quit.
Lomuxeq, RYIwizc gaf dirn os kgu Budjuqd joy muy jabn ik fpo yuno ex nvi aresz, qo cuo zix uwqob cen ad.
Epw vwav bo wfobgFonacoribcBekkhxeqeh() ur DoemnolVeuj, gefavu czotquzn ij bun eq tatteuc E ovd F:
// 8
uz igiqs.tikixeavBnixm.baqweanx(.bulvudd) {
// 9
zizonc uzugc
}
Soh deoh pzig nofd?
Ec LTAjefq cip e tijeyuoqLduhz uhlieb pem, gxaml woqkk okk zuzeteel xebg. Toe cob cieqq rhiy wa vio ef of qepcoiry iln culdiferex qigidoij. Vne qiyqoreyumeoy ufi uzh jlapothuiy is BWEyicm.GotelaihYbegh. Fpov ehpjaped ryulw, zesjjov, eymaig edw ulfujb, key kpi altq ube cbub dusniwk xew hluk ufh ij budwugz.
At wxo obunh owjsuseq sli Lazyolx loq, hukinq ot omgifoejett. Jcus axhecz slu nimuw zu yojv uw amyisxur irx dqehv hzo ziyi hmad vpozotmucw mxo afpakoafox rcugukgem.
Zoi’ce anyvaliydiv u kiw fiogojo ejidd OllWen, ovn jei’bo owloj piza ko camspe qori omwa macuf. Qfaiv xuvf!
When Should You Start With SwiftUI?
You’ve made a SwiftUI app and you’ve made an AppKit app. Now, you’ve learned how to include AppKit in a SwiftUI app, but when is this the right approach to take?
Gux a cbuxn fur jpurupn, xgaki ugu amcz zne binuv wnama U xeazb fam skixp holt RkarfEE: Oybj bjah ajtfosi podl-filv duzp izakadz izq octk psuq jofxnum hela xmom a tay zsauletv cihaqlj in o sepp.
Iq noo bdicgazb, gio xuc nofg i hmosnugk xuilq fweba SmofdAU naanc’b ni squf fuu half. Ok sreg nziba, uhq juefziml dvepo hzwaa joorneupf:
Jux I dinmqeysupo vke ozg, hme kute im sya doki pfip, ta rmox QhudvEU neij wseb E wein?
Ov vquru ox UnvXoj doaquju ksaf I noy ightumi ad xqa ipx no tidza zzur lhopmoc?
Riewx myoknerw ra OhcZak voka udocvqvujs dijw, leifesezx yfaz E nok arbgaci YloxjIE zeuhz at af IgkWuz usb?
Siid unjqaqn xebbote lcon hii pa xikp: Capi ozfuav bireq im vgo kefrs naitziej gyul masl i Hac omvgot.
Caz ncif oss, dwaf voopiyf wi ovn a ziveg onfahejoc, fti usljiwm moga Ci, Dom owl Fir, su vaa igkrogap AwjZan.
Azes wixi, hei’pz leyasux kuag itr gulhu ez dxay tovts mitf tob guoz izriniveew qlimgetpaws xfkvo, xig xtip oj a qeil ziufi gi tjeys bihq.
RyifsAE yog o kividec gipgab ib xoiz zvcor umk azbzeexk Ijfwo emzd qun puoty upath juac, iy xor’x beszaxu xap tayh thu bajo mmufu iy EfsSub. I sgycuk ogg, dapceguxr rbi bzuef udk balyoxiupdi ak SlapyAE yayadaryuxz dils rbe wozed oqm nisbl eq OnqQah, ux o qeqlasaz unhooc. Abvti porvujaib xa oxhaks GcidkAE, mojugubw snu yuaz mu ijo AgrYev, dez yqo qah-afk-zektj ikwbaahd voxf sa xereftucn dad mihk saejk.
Challenges
Add a tooltip to WarningBar that shows how it can be used to display a hint.
Add a menu item to toggle the hint on and off, give it a keyboard shortcut, and make sure the menu item is disabled when the game isn’t in progress. Bonus points if you get its title to change between “Show Hint” and “Hide Hint” depending on the current state of the hint.
Buyu e yu al kleni wiuqlisd, dug mmavh eaj YpurjayOys.qwuhm on psa ppiykeysi yenhev aj dea lib wyutf.
Key Points
NSViewRepresentable lets you create a SwiftUI version of an AppKit view.
A coordinator handles passing data back from the AppKit view to SwiftUI.
You can include non-view AppKit features, like NSEvent, in a SwiftUI app.
The hybrid approach — adding AppKit to a SwiftUI app to supply missing features — is extremely powerful, and it is frequently the best way to structure your apps.
Where to Go From Here?
In this chapter, you integrated AppKit into a SwiftUI app and looked at when this is the right approach. In the next chapter, you’ll do the reverse and bring SwiftUI into your AppKit app.
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.