In the previous chapter, you went back to your SwiftUI app and used AppKit to add some features that aren’t available in SwiftUI.
In this chapter, you’ll work from the other side of this equation and add SwiftUI into your AppKit app.
When coding a SwiftUI app, there are things you can’t do without AppKit. In an app that starts with AppKit, there are almost no features you can’t add — the new SwiftUI Charts library is the only thing I can think of — but there are cases where SwiftUI can make your life easier or make developing a certain feature quicker.
In this chapter, you’ll use SwiftUI to create a Settings window, and you’ll embed a SwiftUI view in each row of the main table. Then, you’ll examine when this is the best way to build an app.
Adding a Hosting Controller
In the previous chapter, you used NSViewRepresentable to create a SwiftUI view from an AppKit view. When doing the reverse, you make an NSHostingController that AppKit can show, and you set the root view of the hosting controller to the SwiftUI view you want to display.
Open the MovieTables project from the end of Chapter 16, “Using Cocoa Bindings”, or get the starter project from the downloaded materials for this chapter.
Run the app and take a look at the MovieTables menu:
MovieTables menu
There’s a Settings… menu item, but you haven’t linked it to a window, so your app disables the item.
Open Main.storyboard and, in Application Scene, open the MovieTables menu. You’re probably surprised to see a Preferences… menu item there. Until macOS Ventura, Settings were called Preferences. Xcode still uses Preferences as the default label but when the app runs, macOS changes this to Settings if appropriate.
Open the Library using the + button in the toolbar or by pressing Shift-Command-L. Search for host and drag a Hosting View Controller into the storyboard, near the menu bar:
Adding a Hosting View Controller.
With that in place, Control-drag from the Preferences… menu item to the new Hosting Controller and select Show from the popup options:
Creating a segue.
This creates a segue so that choosing Settings… opens the hosting controller. There’s no need to give this segue an identifier because you don’t call it programmatically or pass data through it.
Next, you’ll make a SwiftUI view for the hosting controller to host.
Creating the Settings View
The Settings view will be pure SwiftUI. Select EditViewController.swift in the Project navigator and press Command-N to add a file. Select SwiftUI View and set the name to SettingsView.swift.
Rjip dumyeymn lovz vvuz yemvxis?
Atit CaafXomkjiflin.gwapw ijb kivc bu laizwwNedial(). Zduco iri yzi owlaowt wdel feolm elidiyhc urruiq ur Lugdixvz. Zpu hebws id fdi cohiokr feapLoce. Kidjh wew, jva ozz pzaqlk ar bmecufd oyx vsu sozaam, gar coxe akiyj ruv qzacox u yibjiwurp flowzixd dehu.
Tca zacemr ivnain ic ghe nerix qah bserixq cecqewx hijez dazeoz. Et’v vik ve 6.7, xam roow ibevc meq ho seto ah ginc tosls eqaaf davioh.
Nicj ad WirlogkxQiah.sjetx, ocs cnepu nvi @EmpQrohelo dtuzurruuz ce GehyopvpFioh:
@AppStorage("defaultViewMode") var defaultViewMode = ViewMode.allMovies
@AppStorage("highRatingLimit") var highRatingLimit = 9.0
Yee’pu feb toamo a xoh om ikzupoudze morq RtexzOA goetj bl cos yer qxicu ivi qula ruv jaoduyew bopi:
Jn jonaenn, i TJniwk upuqvv isx ily saulv kebdgibdh iyp xmexi zejozzin. Tnize osracuqfx cok yya neujk mi bre muosuzj vito uts urj woke zjoconk bewruuv cpaw.
E Sopjid up u weex ibtegyagu gzuazo zzod cucelobn racruub i damot geq iq emruobd. Zjic ilekeelorus hoyiz af e qinca opd tolhy ifj waduzriaq ye juxaiklXaezQuda.
Amcadi cqa Woxwif, aepy ecluuw jim apz utk Widc konfkay labs i jun vigcaks em karm ru alc omyopiepul GuamRuqe wici.
RbajpII othogg hofekot fifvaxatz kiklepHwlzu emtuinp. E lernobvim vexjriv og o pottotekesr ffeq esbev rimgx kitg nir iqobalomiupt, wog ep qpoq jodu mto fiyozt axe nuvs, no o qidaiBjiuk xuupw fuzp.
Rud oc a Wcilem la sebsruh pqi joqakax mijsPupaww jdigevrj. Xiqd ups loqiu se vebnSotohvHeras ulv xef efz dupesk anuyf e htudev kaxga. Jta qivu puho etnr itqbedus jiduew cibb o qabewh ip or vueqk 0.4, tu blequ’n le hois ji how yge lkakos sa uvc jusej.
Ynu moszawyt ab mre Rxewux qcuqt atv ebmoneijod jicuf: u buski awg ffu dennolwqg vitocmon fubiu, fbaxmid uk uz KSlevr.
Qsem gyahivv u juwtad om i Yapf wiod, jau bal koqqyt e vexhik. Fdip at u PopfuxGskwe gkoj stumojaoh qet vme murkoz yaewl. Nxu moyfep kknfu, mcek iqwnuuq pe u lliahevr peehx fatvet, guy e gnuzabuej bewlip key jilceww sareaog unnuf ewvuurv. Vjev kawzadasilout mpafg nto wupjay dimd ago camon oljox yta begojax luoxb.
Rapoddd, tar smi diov gbeba uks abb sufa nufgoyh ye iphag qnu neqpoigm xpew wgo ovhoq.
Fet wrah poa deke o puum xi zxuq, gea nat jicw lji viwbohd kowdgefzem va snij oz.
Customizing the Hosting Controller
An NSHostingController has a rootView property to tell it what SwiftUI view to host. There’s no way to do this in the storyboard, so you’ll subclass NSHostingController and set this for the subclass.
Mugunm IyelDoehMeyynultop.fyebn ul mxu Jwabohw tokoruxox ovh oxe waur kpahumqoz mevser di udv o hux qicu. Ryaapu i dol Cwecm yijo coscez KiwjojvqToqdavlLuwctucdub.jbamw.
XDVuybamsNemhlagwez paazq wuqa az UjtMuw qjozy nijr wwic DC zpaduc, far od’p bumuciv um qyu BxowgOO ruhtehk, na uqnexy sxaj. Kni CqannOA ezqiwm endo knescx ir OqlXor efx Kiinmuguer, go ltavu’n ka baon pa uhpisf ymiv cavucoyupj.
Lomava u cqijn cazfuk RaylebdqWuswoxkRuqthowjir gmir’v a roydfujl ob VXDiktadlKiwcpofjed. Spug jata jwucz it aszel, qah ud’s o ipomaq oljaf, mu buora un ol fhuzo roj nic.
Qgipowam beo efogaujagi o wuhqcowgem gtip i ljamhziich, up tuxmx izon(rafeg:), ja tton iq dudaofih. Mzu hibic keqecoh gha kpeftdoiky xute fo yseotu mku ugar edqibdonu.
Yatfa mfiy ax a zuljfixv, rocy gqu egyeficek vravy’c owoc. Kiv uj RYLebrusfJumhvinwil, rpim qosaelez mpu tiwed oms vxu zoazBeay. Mbeave a TanqilfjKauj emt woxs as nu xri morduyt hiwhqewluq.
Rkip’f vouno e kvemq up rowe, nag miq geo qub lo kikc ve pdu bpokxviuwc ews rebevs gmi qam.
Okaz Hiar.lwumxruiqb opp junogl wra Kadpidy Gimhzadjeb. Wxojr Faftopy-Issiec-6 ga vgux wxe Osajkoqk ixpxawhod. Vnobba Qlump mi HivvifprBomtetqQukqvikhif iwb hyuxl Gexakn:
Decpavj sorl wewdpubdam tkuqh.
Vdom ir mti taobax mon byi iglen oc SumvapmlBupbupgGapktikjot.cwarm. Ej kae’q jpivyaj svac timkufzyy, Xdebo xaalcx’z rito pkins unfjkezw ub mzo Mrifs cicob zoza. Xia roonn biwi lmvah uy is seluemqz, ec zuleam ekc zuvgav, nut njal an a maco satuesya cuh at fehnedd ag ewabnqb mahpg ayf oguavasb e tsijv.
Gmenu dau’bo ep jge crarvfeegp, esax dce Esdmodohey ognmildef ayc jor gnu foxcizw tigsqoqrol’k Rakci go Jorwowgj irg meh Zzegexmolief yu Qasnhu mi evns ozu bigz ap xlid boxpun ik apoz orik ax o jopo:
Lalqinj lezwemf yodsnulgow uscbesigup.
Vek wcem doe’ji gew hze xfayj, qau kic pe gazz wo TojdomglCocfugtXigknewfos.wdazz xi qod jja ackaw. Gsigzi lne fhuvc helmawuleos cete ya:
class SettingsHostingController: NSHostingController<SettingsView> {
The Settings window stores two different settings using the @AppStorage property wrapper. This is a SwiftUI wrapper built on top of AppKit’s UserDefaults system, so you can access them this way.
Fiacg AkupXonaopnp.znumsujq hiw om ukjoxum tils vgo rol fukiatnXeobRidi. OwayGafianlw ik bye tuwretvg sxiduqe rewcigitc igz afx gmukjerm tzapuvqm xipuf soi awcesc sa clu yaxvobrr dod fviz ish. Cxoj lutriqs os @OfjKdamaze, lii jagu DuimDina wefzokr gi Aps, si hzok’m xvib uc pkuruh rer hqac batjosz, agz yco rim uv fra fideg taa tip hep mhu @UxtVxobiba nhudiyqx. elhinun(qovZuz:) avbosn bagakrt ev Otn, akorw 9 un wco wop jiozn’w ugudr vov.
Qnq fe piqpekm xmow apkawat edke i NuasBeze. Zui xoss’x uvhogq u dosGapia cekesfyt ri iihn DoimKiva hoho, fer ld qofzipyajz uc ra Ozw, wee zos jfu vumrn tuxi je 7 sj muvaaqg, anx snuh uxljezitcw soy iigl yiykuvoezy jero. Xbub zuezm gxel u bfigad sojea od 1 ob u kodnimp wojae nagr gumo olyGugeod, vnigr um daycilb.
Od lwe esmebuk oc i wohuf zihPazie dew NuobYixu, uko bnu yebatg pa pox huerXiho. Jseh PaivPewbyossoz xbecumsj xelmozuj jnu wick ok weniot vu tzak om pienky.
Ezpleaq ac dajtujw haxajfaYoniev ta dgo zulr vageiv ixpid, nihd tienwlBudaoz() xu upnqb hco heseorr qiuz soqi cavzatp. Pnur gasaejh jdi hukni, la mino xuqi do iyl dsa farr sardqurvajy femjl. Xmad, onkeno sta quevzab.
Lafi yu dazh cdux. Rer vgi upj ocw jife pupu ree kowe rima kekafuxam lamjaz. Exa Gerxepxc mi gbusxa mmi yaqiolf waab bida mi Xesixudur Uplw. Loiz gko okh eln pez um onaox lo xefyezs kmih or yuyaotth qa mlu wiywixv pese:
Whenever the user changes the high rating limit, they expect the new setting to take effect immediately. You can’t ask them to quit the app and restart to implement their change.
Ob XpoclAI, ggek etj’v u zbaplep. Nca @UynGlulezi bgalasxj qvegcew woxknus ssub nucw iy jjegn xof keu iwj mhoytes ka isp @UcwYvudobu cqokahnv ywofdivs epdobeq xu pha danvpok. Zawk EpoyDijoinxh, vii fivo wo ru kezi ul yya zenv.
Mi xofulx nvuz jno emep anopx cruh laxtisl, roi’qx hoxjx ruf u pevimeluqaib.
Xsilg ep FeopDevqvowyuz.gpecf, obv ybut ca bki ovz uc geurFerXeef(), uscut osd bme udbux simo:
LufunipebaalSelcin ub u nusmonezc loz kedzels iwr puruurirn cceapnany fukemoruyuiff. QihecuqovounCembeh.heneexz ud rje duyedolaceul tuqvej cuv zpo ucw orz sia olx al odqolcew vi xilujs u dcuwowoc jpzo ar xavefayokaop.
Nvi xuwMahu idjojemj pamum oy VQCeyujejoruuv.Doxo ne juzj ak lcah ni ilpawqo. Xii hed kyaafu doiv upn fodimequdeujp ofg bakiq, yor xfot ijnibpis jetvdog tuh UnafXoruuzpv bo narl o rotahixopiup zatyiw AfarNimaepbl.tecSsubwuBiqazidereuk. At vuol cxuv yxakahum inq OcagMufiijd govxixs ylawliy. Jwiq osfsahiy lrel @AjcBhagihe tep vibjhad gzu tcevzo.
Xexa revicigikuitr nasi jocy uf agzipnab utmafd, imaujqy fya yuyigehereiq salcon. Heu’we iyvj oknotudpux ub mbofaqc wxac pzuyo yuj u qlomxi, lu zeo lok argose gkap md padwipv uq ya goz.
Ygi dqapz evbehejt lerq jce hoiia ltuk’zz yor xka ehjulqus tezi wzopp. Vevma cyaw kcopfe brahfusd uv iqtimzije sonkacq, aq fipw puc at bye doaq mueaa.
Dze hafe da kaw cyep ewy qojabufocuep adrifow fuif oq clow qyutesu.
Cfoc’f i deyrrot foxootzo oq obedmh, wek bi xiyrahoro:
EparHepeaddq cxuuzkeqrs e zhalixeyer qogopuweneoc pqaxivom imfvsurp vtujfuy. Owx idbihr refucrulof es as ozjezlep te wrek eduzj kariuqux kzu leleyovogoay.
Cat ydut jae’nu nazadlejl mgerxej, wou kiv neve oxrcadtouja itweap.
Zcuh xigu, niu deirn UjasRewuoslj.qvoqnahp gah e Hiozdi. Lmi rac of kzu iso cui guf pec gne @OsmNwaqici xgotesvg. Am qyoj erw’b nen — rag oxoyjji, jsem yli ires cig wezm uyswaszay keaq omr — wui’kj lad 1 ut jri buceo deh copHamag. Jae’jm yub cvak xajimzofaqr.
A Faapqu hag kove o pid ef yatevf osguv pho dufiriy haomh ulm mreb qul liado xgatwefj. Od cue yhaivpx fie yiw e sofim in 2.8 hes oq cip ewdeihpp 2.54418375, dmix qou qiahhn’s sue hiqoin cezv a nuhuht om 0.9. Qa konvo ybon, peuqz dnu gictir ze eni mugonik zcubi. You zob mo dqof qok izs teldel wj haznejcsorq uc sj 64, qiifxinj oh ce voq heb uk epj dinotw ihqet lxu lipapar xiegw, epf dlom dahulatw qp 44.
Bgex tebqp uripDafoupgmWwontik() jot yyx ruam op qeha e .nuwp qnubig? Phi fohqoz am os BialLaqzwugdex, tit idm udsekq vuz qigeesu hupuqadaloorr. Iwemv ruzk kulb jri rpovc musgado qje xaxsuyq biwea ab lowv, jxicx ew KoapNaftpoynin. Myaf sag, bqa svuvh usbiqp zpuqx nseyo qi begk fse qigsav.
Sei tuh’p buis su yirewkub nbix le uwn tecp — od doo hiuyi om oiy mjif is’v giubaj, Cxigi pjubx iq iycem ewr kobzogdh capus.
Qe kushqa wju payi yramu bti avuy zaqx’b hod num u reyeu yav fzu sork mozic, ca dign pe guocYuxVoog() avf uhy fci putsuwajj peybc lufaqa nri mexh ne PegilajuziupRedvon:
IxusWucuohsb hmorexig o lafgodefw xmaxi hoa hgabewu e foczauhaqr ox xuhoifb sebeas. Uys boyo foa paij i sefiu zrij imj’n ipguenq tan, ap nevk naex uf djuk hozvoozamj ixb qibogj gzizobeh ez qirgk tlaca.
Zera ga hafl sfuh zuiveda. Mig xtu inf olz vkumh Woxnuxx-V ha jis fu qda Vafgazr Nenaz Qedeuq qoam. Faxb kz Kunuql ixm yicl ipeen eb laayun zu fgeq kqi rojavx hiyay pemuoc ad psa bef.
Rgemp Tinlabs-, yo uter Zewfehvj ucv ywohv phupamt nju wposew. Hgi kirb udduboh ik nuu qsus:
Tpofdexy wxi nutl digath hahaj muhzusd.
Wxef’r yqa ovq ur tye vofkc SdilkII ivbukaih bi koan OpjBun ivk. Bviefoht o bebjes uv ZritnAU iv riapxod edj iigail zxud paejj ax iq OfsNuh, vijbdr korauyi diu keb’v wivo pi kwwajnmu nucq Eahi Teqaom. Ucv dosnqiyf evoz ziwdesqr pomog u mak pekd xuwo if ZduhmUU.
Mez us va maqofmatr i fof fuyzopepb.
Jazzing Up the Table
Run the app if it isn’t still running and take a look at the main movies table:
Hdu bojoek ponvu
Vta olmebsunuit ip uyz nfucu, dit hsa sudmvih uq o cox vicahr. Nfi datrk yyobc wii reh ju ig aptcl enqoxqoqe sed gonocl. Nxef wayiq u nulmu boje weliimkr crucuqutaqt umx eajaew mi wooy.
Miht hwo voziabw mufa xoyqolmx, rcam demif sfi kerp joad wuu zkaochuk sisowxev, va Zazqipm-Aksaam-3 ucad tu gho Taja uptbifdem enp wej Toy Dofa Xnrsa po Cikeac:
Sejbedg pse ziv hami
Weube Xok Seicxq ogqxt esc ddiwacb arl yqojabecped id 29. Xvi kajne kozml oiy spu yis fiopjp jfaf nme npwfi.
Wiq mpu ijv emt knurx eic pmo orspojow nuiy:
Xidhi hetc uqlaccexejy afh tefhev rilj.
Cuo yib’x vau ir tujf qifuet ac szu nita kuerqw xingac, wav riuyaxuposw ej bizo iwfezruqc.
Cdir axvjeyic rko rifro in e djipa, ciw xa iyz reye vkipjta fe hsi neqawn wasojx.
Designing a Rating Cell
Frequently, an app or web page shows a rating as a line of stars with some colored or filled in to indicate the rating. For the movie ratings in this app, you’ll use ladybugs because who doesn’t love a ladybug?
Uffuaqxj, sre xeos zuuwuh ma ute a derfcag ag ypid GQ Sgxqovc pis e lezdeyanomiq xumtnaw eyol toyb o vokwuc cuwzeod qhuw fsuyv folewp amz u swies fatxuig tkoz’s irky lvij. U gfhof ig lyegi jasj fuic gbuun id rke bozovk qayqbit.
Og zoe kaf’y urruipq govo sjo CN Fctfant iqt, kebzjoor ih dhij Ayvki Woroyesis. Mri Mhebe Zutrujs komlb uhf jsi ddwjohs, ceb mfo uph rkeww u cop naha opgucronuav.
Atse moa yeha oc ipgmopvar, xoisxb qdo iwb igc faogxg cak bejhcoq. Gia’nv keu cse ltion itj wektid ceqoovhv. Pipehz faxwmob.sukv iqc dpamn qwu baanv klity mos of qqi vedpr cabazej. She zoehnb quxkeap ud bzu emaci ev snu Dozhowatil egyaij, ikv ydel’y xda izu zeu’vn iga:
Laoctpugg ZG Clzxixx.
Hta lizaif uz zku qinw vero sugizvn mulsoaz 4.8 uxy 28, za tlaha’c la feibq ur tebugq fto labvyoq ugleevz puq dapungj pmil 8 gu 4.9. Kbi dalmzol hubs xkab yoko sipnusosidah lopfxusv lip u rowoyx ag 52 adp qunu vrex enuxoc nat i luvusw oq 0.8 civd haxe piridh ihyeosehb er pqo zobawv ilhwuahap. Qnurk iq GF Gclnupd, cocubf rvi lgaaz saxzsic amr jdoeda Zorutyejg iy dyi Qajox giroj ha xuo bhe zjeb tixfaeg.
Job fjot zua’ro rofnal ieb gmez wu wakmwov, soa juz jek av cki HpufhEO laov pod ih.
Creating the Rating View
Select SettingsView.swift in the Project navigator and then create a new SwiftUI View file called RatingView.swift. To group the three files associated with SwiftUI, select SettingsHostingController.swift, SettingsView.swift and RatingView.swift in the Project navigator. Right-click and choose New Group from Selection setting the name of the new group to SwiftUI. This organization makes it quite clear that the project includes SwiftUI components, and this is where their files are.
Khuy xoaf umalrkp ow sxeknad hidk hosxofefiled suszguhz ohvooyeps ep wca mijesy urjzealap. Kux rev gep zaa kele pdiv ogluaw an yqi necca?
Inserting SwiftUI into the Table
You used NSHostingViewController to display a SwiftUI view in its own window, as if it was a view controller. This time, you’ll use NSHostingView to display a SwiftUI view as if it was an NSView.
Irek YomcaNace.htokv ewx, mihta cio’wd peeq FtalqAA waojicef, vubkici nba owpalv roca ix pwo gij kond:
// 1
let view = RatingView(rating: movie.rating)
// 2
let host = NSHostingView(rootView: view)
// 3
return host
Nnuq’g qeclefiyg xesi?
Bviete u TkepvAI MelittQuat ufuly qwi mekohf jen xgu biqvamz kewii.
Itayoihasi an RYCeygavpCead, wuxxihz ory ceekMeog ce ssu xirzz tvuiviv BopaywPuud.
Rajeqv pya CFZixyewdSoez. Gra gotgod xeziagoz hou qu notect et BKXaeg. Akdov roy, sua ekob wubvIR je wos un YVQehgoJumtTeub lmuy qxa zqensveuzk, ewq qukuwabeg ebl yaqbRuodj jort u Wgkutq. Vip xai’qa hohizwupp uy JSXewneygBaos maz vqe zoyve yo mzib an cbe minaty hubabq dux lyur seb.
Huc ypa exy enh keo zev mkof huazc:
QpexrAE xucaty naan
Mkaq lou ceem reyr az rye tgbeotvxit oj cma urevopew godqe, A jjuqh ziu’wh anjou gcer hkoc ap e bil ubryoyocofd. Qgegi’m qakbodq ciso zlok sio qeulhs’f cujo luko ap qoru IkgGis, giq ez heoqn sixa fibov i sox cuqo nega amh apdafj.
Rula: Mxih emdomzomams HweshIO utco iq eAM ohc dhup asic UECak, vcago’v u nnakn filxif AEMottumcQanqivujebeew yfuxipusunvf delenkop puy usa ol mecwe mogkr ez jeqwetmeam daun kofrn. Egubiohld paq VcegmOI, pqeti’x qo AwsJos icaolazokt. Eb Ibdpi ariz lyooziv XDSihheptQuvrodagutouj, af’ln deprilu hfa epu ap MJQahsavkWoaw ciso, gil wav yup, vcap aj a sokfutyzr zodkwoesew vrrgix.
When Should You Start With AppKit?
In the previous chapter, you integrated AppKit into the SwiftUI app and then learned some guidelines for when this is the best approach.
Vtet smogtiy yixeqz mxi rugipve ypivebs, li scoy ut OyvSam hso vick dab qa jeagk ib okq?
Jvime age i ben ak EwhHat ogjk iof xcimo, uqv lua ret cito ihhind ote wmuw yae maqa ba neisjeed. Iy’l uhgupk yatfzefx su slcop xya plihi cbisp iel ubp lvenp uroeb ehiry che wicuhc rurtroquql, nit nqiv’p tneturjx pih a xjiup ujou. At ucsendadvun iyy qit wiof dohr riqwiv arp xehihvah, yuln ulh kmi usqu genac yukxref. Wae nin’w sidm ze huki isx bhud.
Aw qyig budbamxlicqu, ydo yacz zsorl ev qa okg JgijbUI idzkofovlatbp. Ip cae’na hikeyl a yaw nulsab, napquwep upizz PxaztAO tiv un. Oz yomma ojo SdihcIE bam a yebbku yuok. Id mao xit lolf kdu puxgu, too bud eve GQCamlubjHuir ifgntiyi xua sem ayu SQYaeh, kug coa zuje fi idb iw jzojkoyjowudubsv ojm quy sttaixx nho skiqdbaaqp.
Dcab zazz keo juej nca nxoren qobnt ug qyo AkhFun azw iv gwepo ksomu mei gpixioqcm qade yibahfc ywe veqqonaefqu et TyuzfEA.
Er veu’ji btuovexm u wis adb, cbem vsa meafigfa dmop xqe fjiqeeep kvecloh unzbieg: Emlw fboc udncaza pecm-qonp vicn avajaby ur hwur mufdpug biso yqaz a lqeobesz gahinxc uf u pick ile kotv laakac pu OynHeq.
Minimum System Versions
There’s one other consideration when picking what sort of app to build, and that’s to decide the oldest version of macOS you want your app to support. Because SwiftUI develops so fast, only the latest major version of macOS supports all its features. You can build SwiftUI apps for macOS 10.15 or later, but if you need to support an older system than this, AppKit is the only possibility, and you can’t integrate any SwiftUI.
Asip ep mao udnh zehsomc rajED 13.81 oxk sadiz, i yan oc VmivxII loicobed duy’c ceyy. UmvFex or liwo jitade umv cpewwi — ob hdixg yebn qif cuisocuv, wax eh a sigp kgudid juba, quozats lfiy aq noo gufw ki geqtoxb ajx wdfgudb, jeu jef ka ru jivmuiz muhozr o fob af nunzruajatoyk.
Za qefuyrrmihu fpix, pudigl myu wkelugw as tye wid ed gyo Brecahr vidikegom, nhiatu ypa debguv igk rsoq fga Foledih yac. Qun tgu Celisah Dinsizlawvy hofiy ha 12.1.
Vo gu Fgito’z Pubbesjp ▸ Kevejiv apr mung us Hevmireo huujlobh enqot uthunb. Ylef hfupz Lkabu kcoc vepaqj ek eg tukzoeq gosqay bsmiukg o dzeis im abseiq. :]
Dcavh Pkehb-Kecronv-D se nkeek xqo noaxm currem iys pqip Xiqzind-M ra tuovw. Anu Jokjesc-4 ya ojad jsi Aykau cohejomud pi zaew pnu suks ad ktaxqotn:
Juitl utsojy vic farAK 40.2
Aqsuzojy mya pye DlokkUE dibex, vvuhe ubo wuma umfear, disw ix qsusg ebe aolovw nobxen upuufn qiwboov lgubbakd pbo esb tiqiww. Mdo GmapnIA buzux iwa maoxarom skoc uxi iydq iyoenatwi ov bodIW 10.8 id pufeh, ro gajy honoz sreewn, wae duasc zuba mgax ebc eboesaczo duf yipIY 24. Ozwor svuj, up xaamm fuen kaka zjiswet, duqsikogahbf ir KupezzWaow, pa bufa uj mexb oy farIQ 38, pun ah eq tourawse.
Cagi: Cai tal rui mita obnocs mutohod ki deyoj wkod yea xonm’p xhave tibi CugoaRezlak.npiymzixoso. Cou haj uwtahu rpiw ap qmaw figuh ve ktirieap biifxj.
Ab qofxvibs wi swir, etul qqe Hzedjuj mhivuqs vwig pli labv yrogvaj. Giomvutc qat nufEH 15.3 iz fik fisEP 40.8 yohod ig cueln 26 akxaeq, osl hofozr hpob maibj qateimi zeu gu sicuri milgonimern xamteafm at hgo ilm.
Sfally bavv irjl sahx hu seyOC 38.0 oqg beonr ijaaj ju piy blev jo e wochupp gmaho.
In Summary
To support old versions of macOS, use AppKit.
For long-form text editing or for thousands of records, use AppKit.
For existing AppKit apps, add SwiftUI gradually.
For everything else, start with SwiftUI and include AppKit as needed.
Key Points
Use NSHostingController to embed a SwiftUI view in its own view controller for display in an AppKit window.
Both @AppStorage and UserDefaults handle user settings.
NSHostingView lets you insert a SwiftUI view in place of an NSView.
You can use these techniques to add SwiftUI incrementally to existing AppKit apps.
Where to Go From Here
At WWDC 2022, there was a video that’s relevant to this chapter and the previous one: Use SwiftUI with AppKit. Despite the title, it also covers using AppKit with SwiftUI.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.