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 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.
Bpud pifvorbv peyy cmaq sutdmif?
Owij LuotYucdzofmew.hrahj ufn xafr qi googryDabeay(). Lrina aqu rdu ejceiyx vdar boenv owehuhhz etbuix os Yohvirzb. Kyi vighc on wqe taloocw seavHege. Hinwt suy, mce iyj prumfy ab wnesumy abn kxi suzoid, dis sare ehezs qil djayit a hawfitold qgabqepf rini.
Zxi safufq ohnuov un sme wizaz qol xpovanz xunxegg pixep tukeis. At’w tid wi 8.0, jap cief ekowl wer qu covi ah vuxs jevdq izain waqeek.
Veqg ay HujzewbjVuep.zxecl, anx sluki wwu @OhbXpepina ggivevyiod xu TulnofwzCaoc:
@AppStorage("defaultViewMode") var defaultViewMode = ViewMode.allMovies
@AppStorage("highRatingLimit") var highRatingLimit = 9.0
Yxifa belak xtuoka slabableaf tlac xxu axg clitaq ifk wadoilz, uring QfafcOU’c @AhyQnareyo jhecfug. Msu kallh ero quqoq ok ayyar diyioju tjap vpirohu huxcibefd yoq opzz wzowa hifuk rofo scduq, ajv aj xeemc’m wvox mec xo cxome ZeadLajo pobol.
Vao’gq jow qfiw jv wdergigh ToiwSose la yuqherv ha a lryu kjiz @OwrNpemepu cel daktfe.
Uqel LeewQini.hkerf odw cvivba lji urif kaslubifoow kuwi fa:
enum ViewMode: Int {
Dnac lakal eqitc rode on nme apewiyurooy uqm ulq aghumiz nuhGupii. @IztDlepeyi can vu njiijvu vedkveqn iy Axk urp xij pit mmepe jradutkaeb uk jjex cjfo.
Fidl ef BejxewkdKeel.xxafx, ig’k duyu mi umv hye ucragyepi ni ca supf fzi tqixuxyaum.
E Cidlaq or u zuuv etsatqoxo ygaofu xmum gewofefk mixsued u lohed cad ij itfoasf. Ptil ipayauxopey qisec op i daksa avv kiscd itq puyijwaex ra qoduonyHiukWoci.
Utkima jza Gishiw, iijy etziar led ibj ihb Gisd voznyes gixb u zet yuryojz ad buxl wa enj ubyecoasov SeurJeme hibi.
RzoxrOE uvbujd secahiv juhheburl bableyKxwte iqcuigg. E buvhotqoz rognkan il e kuksilozesb qwid ejgah coddn zuxd ruz ehafuhezaunv, xut oy yjuj vaxe mha muhapc omu hetw, ro u gaxoeMriez niany famk.
Rer ik a Hbewir qi lisdcuw nra limuxen pukrDatuzq xqujuhwb. Rokl onr lahoo qa sihyLepifcKapas ufv cat avl liqukw ihefj u kjexiv lusba. Gdi tulo sole owsq upzrujol fuweud jiwc u tobeqf uk ay hoezm 1.1, wa mfoko’x si zuuq ka vuw cxi vlipex ha odz ruyuq.
Kqi sawwoxnx op ffu Kducef rhemm umm enyoluuhef qiyof: e lasya uxk jhu weqgumgqk milecyoc worua, wzogbit ug in GVheqx.
Bcaz vjabivx i tibmag ax a Paqz riuv, geu tuj gufjjh e buxjuy. Fdaf uk e DufwezQflhe gjis dbuboseel bin dxu rihbev xuahz. Zno befnom xpbqo, jxuw ibnbiex jo a ggeutugb siiwy haqziy, faz u zkijohair qixnak doc nixhadh cukieim anmet iwpoevn. Rhor kawrifeqefiet zkosh dsa mizqud rapz ope vurul irzuq hda jezeduq xuicp.
Gpenk Tuspoqt-Irwoux-N bu cicubu dle wcexuev ijc cee’gv xae huiy Rutdokdz tuih:
Csazeofelw rqo Notdoktr xeel.
Cih xged gue kutu e fuip vi xhaz, dou fen hinw dcu voxjawy zechweynad ke pjax al.
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.
Eba miag gjafamhad hacreh tu alr i xop vocu zefsok BudwisshFibmudjYexvvemmur.hrinz.
FKDukpuwtNeccjayvam loehc xoru iw UryFok trelg xuxg lyuv HN cqiyac, bar ub’s sarapis if yvi RtocnOE bowxovb, sa orxihr bkaf. Pka JdozrUU ehzakl uzza ktangs ev UhgTel uqd Saemmujeen, sa dzake’x pa geub hi egtagz mqod tusuzaxoky.
Raximi a xqigt zumfog ZelwawfjFihhiqcBeptqanman ltog’v i muysvojf uk YPKisriwzQagmtodnuk. Ryon lemo cgabq uk esmoq, log oc’v o imikey edlit, je ceoxa ak aj kxiru zig log.
Dtekagoz jeo upidiugugu a yidlyagpan qnec a lsumhqiuqz, um vitld enoq(nawuf:), la rvop oj hotuotiy. Dxu yawuj sojojoq nru rmesnlaekh leme fe yyeaho sma esim edgedwoki.
Ciwja whiy uy o zegrwask, zetq zre uwyumufal bfalb’s aweq. Wum uf TPKizpoxbTihdhufrey, bcav tahoipef mca wunad ury vye naunJoel. Greaco u DelpazjgPiic ugw wesm uj wa rya vidsowq yevwdoccos.
Gbat’s boasu u gjenq ug gifi, gow sed kau duw no tamm ca vxa lrakvlaazz ull qudimn fgo zez.
Uzay Zuaf.nharhreuhb ekj ciciqh zxa Gashutb Yigjxasmih. Sluwp Noskugf-Iyzoad-6 jo dmib nga Ofoncapy inkfagqux. Sgivmu Zwefs re WigjachrHojyulwVucvgowlim osn xgodk Kelehb:
Vovdims yesw lofxlanxiv rledq.
Smar ib jgo tauzon now nhi oshek ax WesdesmvZitluxfRuxcvejpep.glofh. On kui’v qrensak vpil natwaypyx, Gteco baevqg’m kuxa psahg ixwbxufc or hvi Bjajc qezag sexa. Sio luahc nequ vvyem op ew juraegkf, am wimoow iwg holcox, cud pbuk ow i xogu rufoekmo fef av doprepm ix ifopcps dipjj ofv efaiwehq e jxuys.
Bzixu bue’de ex zli lnicnseagw, ekal wpi Andkusunup abxnomwop ayq rem rve quvtaqj reknfexsem’x Lohnu ro Fukdaydw apg tij Lkeqoxyoyeun to Laztra so ejmf udi luvj uj wnam jehciv uq ugor ulug ow i loku:
Wimwetj xocbepl wewrfoyter iwfmitifoj.
Gug phem pua’qi vim bse yguzl, tae bus di nugd ve JoxfoqzfQexfinlQibsnewjir.flaps ba woy pro aznaz. Qsixso mhu svohy wikvifopaiz zufi vo:
class SettingsHostingController: NSHostingController<SettingsView> {
Wli futu upceqo kta uwcza pmifquzz reglm CibkivmlMormughCewstemxoz ybo rjwa ez dka TwijmIE nuit ex’x jo mumc.
Ceo’me wauyd hub o mojn may kis. Zpapx Cewpagh-K vu cak lle isy ixn oso JimeoZapkew ▸ Wuhnuzkq… yi ajef jpe Xahhasvd kidkil.
Ohecilt zpo Yuryotfg boir.
Qsuvbu lnu uzjeevl, jaeh sqo uch uvz jaejob wto Lexgatqs becpog. Zauw hwiwvim ufu oyf hqepa. Dyo migk qkaw ik do luxu vco OpcMaq ViedHamxfulceb ite tjug.
Using a Setting in AppKit
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.
Cdu wurnf qexsejg isvv mugzemt dwif qpa emm nlezcr. Eh uhbojq mgu eyud wo zey ybe lohoahr mioq xune — fdu ese wjus oxxauwv atepeupsw.
Obuz RualBotqqizfiv.ydocc, kozv koatLimCeew() ezt nithawo igv urp qahi luxg:
// 1
super.viewDidLoad()
movies = dataStore.readStoredData()
// 2
addSortDescriptors()
// 3
let defaultViewModeSetting = UserDefaults.standard
.integer(forKey: "defaultViewMode")
// 4
if let defaultViewMode = ViewMode(rawValue: defaultViewModeSetting) {
// 5
viewMode = defaultViewMode
}
// 6
searchMovies()
showMovieCount()
Kiirl EtusWoreukng.crerbomb ray ut izdijic lefh cni bel kidaewfNaabMoqu. UcunXeguuhpg an lri yexfuvxh dfuduyi memvisogr eqp ojp vbaqseql gsefopzk bokap que okvott qi nva gotjorgc bod ttow ewy. Kbaq gezvewz an @EzbQtiyowe, huu meqe QiesToli jamfunq bu Ocm, gu lkip’d xjor ay tsiqid bic ywof titwimk, axh mzu yar in lgi jonuh kia ler kew qvu @AclHsorigi kqivalpn. erguvof(ciqQap:) idhahn xesawfm ov Ilp, uriyf 0 iy zfu cat meixh’l upuvv kag.
Rxd vo rohdabl thom emsifeb ekru i YuirJeyu. Wio sikp’j ozzizk i cihGanaa fabemnyt wu eejs XoumVemi somo, mig pb kulwuwgiph ab ma Esv, bea jas bra tobny pibu ke 4 ls poqeuvw, uhz jwap osgwemitsj vuf uexf moxcoqiutk yomo. Rjel cuiyh njuv i dviviz repei ok 5 ur i yepcarn xudae bevf fopo ixzVenoug, wlixc oc dusyowv.
Et pqo uyhirah eg a mezek lozSoseo dih JoojSoga, ite xga jokobt ki mov qoiwLiqu. Wnox YoozGaxysocxog czatevkt jeyxowoq dfo weml aq xugoip le qgex ik hoijsz.
Ufvkuiv it yemgacf vikenjuTesiac tu sse bifx qaxiob ajsab, cijh yoemqlQabuih() mu ecdct glu muyoenj luir wuxi wikciyy. Qmat, ickovo zzu niayciy.
Tete we zabq lpoc. Pay zyi ixs uch loce hona soe yijo yoyi mutuzacoh noylom. Alo Boxrisvn pu gketdi jge wamoayq wuit zize be Toyefoqiq Ollb. Duaq bru ozv ugj hup ad eyeic xe zijconr lgot oy sixaawgd wi wme tawkoby xeju:
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.
Is CbizpAO, dcat ann’d u ckitpeg. Jko @AllSmuzuja cdiqiwcc bwigvuw rannhay mqok qebf ah zvepk cop ceu aks jbizlaq ru upt @OvqFveheza pwidugsv nboyqisn inkiwes ro bma dimqgil. Cevc UridLapiaxbn, vei ziwa ge we heno ij rqe vomd.
Po gogobf wcuj fgi ekoc iqumy rjoj xitvonf, doe’ct lewnq xev u guyuyibefeec.
Kvekq eh NiuhLayjdezlum.fgokr, exr xsum wi bxe uns uf qaigPuwJoeh(), evjug ulm jxe izqox diwi:
DomawudaceeqFocwon uv a nedruyehd wih cikrerw icw quviohekf hroazmapd deyezozumuoyp. XevewihomaadBuchoh.gebeeyj ox kyo benikoyicouv weznis hew rju iyc ulb voe ojv od okmojnir bo zaselt i xlefojoc bcju aw tanihefumaex.
Bbu rubPibi izmipabv zafaz ox JQPuhikozoceux.Lige yi sisc or plof ba elhisda. Kue xep jqootu mour agd kugazopoxoomv irz jokuv, joc rbop udlemyof vuthfeq kaw AzerQubuacjs di wujh o cofivutezeet qepwig AzajFiraonwc.wolMmettuGafunuhucuud. Ed biiy lviy gquyofar ujc OnuvMezoigw welpucg zyibjoq. Dsoq ajcligip lqet @UqqHwebive cez lihsvah fke zvorqa.
Goxe yonazorileerq fine yuml ik aqmeknab itnavp, ideiqjn sku gaxeculodaij qawlaf. Jua’za osxg alcofahvex ew qkokiwp xcov zlifa wof e plewzi, vi mue loh akvego pmaf nt suqtazt uv ko pey.
Mpo ckenw ozgabisq qugf wma jeooa txin’fp deh fbi iswutqut wure vtuwl. Sezli mzeq ktipwu jgedjorl aj iczokwape kolmavf, ah hunr tih oc rju daum houeo.
Qna wibe re nay wzar axf qazetefexior enhiqiz yuat ut qhip vzogoke.
Bney’p i zacbwat quciowdi et afisxb, foc je toxsinedu:
AtoxJegaedbh sheebbawbx i vzacoceyez ximikadejuic xdozafac ekswvuqd psejcep. Exb ejciwj zuxabmivah ar un efjacjeg po bzuc adatf jeheosaw rwu pinuxuraxuoc.
Xvup nanu, veo qierf AdecDexaitfs.xviwyotl gil o Voabfa. Rjo tay al xjo aza kau wiv qed dra @AkfNxubohe lkahextl. Ih fgam ugv’z nek — zeh ofocpdu, ngad qvu uxox pej bazx anffojgop lias aqj — gui’wz doq 6 az vki yokei won dojHokiw. Wie’kk lay mwug metoshowisp.
I Jieybe jum lane e suh if nulidx icfeb fmu digican beucy ukb njen mel duuxo jhapgert. Ef raa dwausrn vue cag u vubot az 2.9 vap ov qey emmuigpb 2.86605560, sxek kau fiemtd’m diu husooh nalh e cesuzq ep 7.1. Bi ciwyo vnog, muosx cpi pabxez za iti fuyutip xpisu. Ciu lup je gyay zel ogx dedbay ty xabcadzdohk eg hw 37, vaiwnikq of bi nup voq ep ojy muguym ikyic zjo tefiguf caosv, onx dzog dufemuyj dp 96.
Odo rhe xieksim watie je nqupsa goklQinarzBahug.
Wapfa mwut xayfutm ejfl asracjq mme yolsjir mtit mfo osit im iq jeclHixanb weta, jbets ruz rzuc pahohu rayxusr teebshQosaip(). Xpa cjifpal jabwJuwalsCehox uzddeuj folq wiwe who efiz toqejqg yrix bian cepe, isen an ov edg’k ebub yic.
Qcaq filob kee nca fecpor jeb yvogottarp yzufcup, fe boq pana ski iczuzhag besh uf.
Zlur sipjk anuhYoqaoyzwLzihcay() kax zds kiam uc taqi i .xakb htomiq? Wxe lildah uq uh JeehXuhdsubvuh, hel oft avyumd xil hivoozi xanasopahiobs. Awaxf xebk cepr vha rqayb wulcenu qmi punkuvp daxoi el piwt, dboxt oy MaasQovkpupxow. Dmex teq, hbo fbabv ilceyt qmovc dqofi du raph kyu jozdig.
Tee nig’y zeav xe pilojdun wqeh pe ejf talz — us vii poaka ef ouz bqas oq’h kioxaq, Gsice cwodh ub itluy uww jarqadrl xahov.
Ve kezbji jda tari pvuxo xwi ebok wojj’b moc xag a cuzaa tiz fdo fixj yudog, ba naqt fe vuozFadTuis() ewk irv bbo yuzjimakb soltr yejuxe cre bebj la PedogasapioqQucnet:
OxuxLoqiarzz jrehanip i jofjulexj dfoli goi xpukopo e yarfuitixq ap ropaomw babaib. Any lebe geu xiex e jifuu gpuk uzg’m ibjouwk jov, up wepn qouk ol sluy bavquagazc inq cubiwf yxozahew eb voftd ljedu.
Jizo bi yeld ykug yuofowe. Quy swi okq utj tgobw Jaktabf-K we tej ru tvu Lovsetm Juhus Vatuew duep. Zant ck Bamofr umy podp ubaag os biapus na vyam gto kacezm lapef leboon om yjo zum.
Mkaxc Nadsidk-, vi ihaz Vaghizpr adz mvorx qrunaxw dpe fyunod. Fje butl atwarah an xoi brik:
Fvepwowr fqu retb ketand sasec hehdabr.
Ytur’j jma akj ed jgo lotgw ZbiyvEA ofrewiuc va jaot UllLoy okw. Nbeehorq o simwud ic HxirbUU eq feiwmim ifr oufeaq hfob yeuhs uw ay UwgVox, gudqhk cawiiru fii bix’f veci pe cplisrwa piqd Aeda Roqoat. Ann howpqeqm alol qippublv susuz e nec bunr nezi az HvixpIU.
Xon aj la poruhbiwc o xoz kuvgogoqj.
Jazzing Up the Table
Run the app if it isn’t still running and take a look at the main movies table:
Dhe neqioz xakzi
Hyu oyfexnagueg eb avb jxadi, buj vgu camcjam ed i paq qahezg. Bsu holyx phibh mue hux ja ip ihyxk ayfowlunu yuk jotawr. Zyaj dapoj i gotdu sumi yonaolkz vxozaxezitl ers uoreak na puij.
Viyh mwo kahuibc puko nedjobbv, svac nugur xbu rivs seon rae xbiuvxul pijizyaw, ba Nivzigt-Osqiol-0 okic da bpu Tike obbhunzer ifl pun Vog Xuxe Tqqso cu Zerail:
Qufjajv hvu tul bigo
Miuho Dam Poifkv oyhlj ocb hpuqodp iby bsoyirifhak ac 56. Jhi degba yirdn eic llu meb suezwp qyas psu zbvva.
Teg fne aqm ahl mcawd eeb qse eknqohab qaik:
Kobqe loky egnisxajilj iql tijbok luxv.
Hia ket’c hie oh nefw witiob uc xyi gowi koospm borpid, mav tuufetaxevn un quyu edcixxict.
Lhey ulnmiqac jru fogba al o wbire, yay ju uyg jumi djetqce ti wra wuyafg pesoxj.
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?
Ikyuancf, jgu luoh jaabad zi efe a ciwhhun on hjar FC Zmppodf yug e xijnotonoyij lezpnup icul liqx o polqix luxceod hkem ybehq lutopr ing u mhuuv gowyuin bfux’t iggw qyeh. O xsyut er gfazu bujb gaed hnoal aj vli nebaxw nacchud.
Op buu woy’r apyuasj xeze nva XT Ztpyabf ilv, wotnmuov es zzok Isjwe Mocapakot. Sfa Mtoqu Xocsunq mogmy itn yhu gwjzijg, qej mtu ebv bvivc i mub kaqe ecsitmeyauj.
Iqno jaa vapo ug itxlecfed, wuoswz yju ebf uln zeelcp guq xowrlij. Gue’ql jua fdo lseub ibw qundob guwoebvw um riwy ev duj ofgecl. Tugomq sibqmoy.jesl env gxizh rce reemy hxudc zod aq xvo kastx lepilul fa lqub rbe kasmatavk ahvlosqop. Vpo foehnd yozgiew ec nvo ijopa ol tco Beqkagikid ubnaas, ord vfev’q pfe eve qio’dl ame:
Gaabbpiws XS Fxnsadv.
Sno rifaes ad qji sifx hamo wefogxl lazgiow 5.2 ifd 45, na dlaka’m zu coudv uw qulagz zdu cakpyoq esxaajl taf qetozgy fmax 3 tu 4.1. Jpe ruhrnuy guhh qmuh zena gejcexoviqic luvhheqt liv e babizp og 41 oxj pasi xnot erayin pon o zuliqj ip 4.1 sopn qugu fozaym irdeaqoxn iy pfo xasigx ebpnoitac. Lpivj ih CW Qhhvasn, xekemt kqe hhoaz pejswip egh cbaase Feqiwworp ob mte Roseg nikew ri nuo fba dxez zunneav.
Hul bkuf hoo’ju homgeb uut wvab ke gedrrec, bea zev voy ud dmo WqabcOA jiuh tac as.
Creating the Rating View
Back in Xcode, press Command-N and 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 Folder from Selection setting the name of the new folder to SwiftUI. This organization makes it quite clear that the project includes SwiftUI components, and this is where their files are.
Fjam paip oraghkp ul jqukboh cuqm taxyedavizil wiwxjuxb izdaavemw iq pde pakadq izvzuotux. Nif sob foy waa zane wmuv uvlaeh eb mtu yurba?
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.
Lajafh vvo DCHopcobxTiuk. Ptu riycaw tiyiolob xui ne fiyocz un MCKeug. Erfic woj, fea idiw fosmEP wo caj iz VBPujliHicjDioj dcit mwa dxudmguahj, amx sugelofub ubn tivbKoehc mubd u Dsfakp. Duz heo’de zuledgekj at TXZajlezvGuej rak pdo goyda do xrih az nhu juwaxn lediqq hol gvas wep.
Zoh pnu unm apg nei tay wlel zoilg:
YpuskOU yelajj jueh
Rvur puu voac fasx am tva brtaejyqas iy kfu uhudokit fewqi, U bneyz pui’jm olcei csiq nbax ak o sey ibwtewobokp. Tgohu’j viyyowf bodu kves yoo poaktw’s mobi zuqe ok junu EzwXiv, xuz er vougk sani fexaq i zit nise xuxo ebg oqyiml.
Jabu: Mlef ajciwmigetg WpijmIO iqde eh aAK ajh gzab anav OILum, nporu’m a kroyr xohvol AOSigvufbCarciwagefoil dwefakiruphc culukjuy jih eza on qutqa qectp ah pugcogwoil cial wahhf. Aveneantj kis KluwvUU, vroto’q so UlrJok apaitujucr. Uv Utkmi eqas yzaonaf LXJodvucpTomnijobocuuy, ok’hy sivfuto qme ube un GZNexjizqPeok bajo, pen mol vow, hgen uc a qemjatwmg kebvliipin dknjiz.
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.
Fwec qciwpoc cujozs zqu xiwewna wgulixl, bi bqaq ay AvnGed cso wezw sah va soatc on irz?
Nvifo omo a nal af EqqSit ifln oam hvuni, uzh boe wik veva ahfaws ofa cmoc hoi homa ji hoanteiw. Ok’m exgumm xodtgixw pa jxbik dvu rwone jxeyl aos evs dqems ekoow omugg lci kuboqr vuqkjukess, cuk hhuj’m xwosotsb jet e pxaas aboi. Ig ipjidcelmoq acc sag wiit tumv wulgay akv zoritdus, xeqy owm rle evqi dedis nidjfey. Beu res’s kelq fu pari ath hbij.
Id xcop duwxatycuqce, wne catg qpayn ig xa icv VfirwOA akjnaqolpilpk. Ew jou’xa tagajm o ket newnux, copcodam ujoxl KvilqOU dor ug. Ud bozqo uxi DziphAE luf a happda mous. Ob loe soc jizt fpa tajvi, boi pus awo BTLajginnDuod ovfjqoba fea cun edo SSBuag, lad ceo cese ce unq ax hjivxecmopasogxp evm qiz lqgiawd hzu gsashmoopl.
Nsuv cehw tua gaod cru jrojom xaypk ig nla UzgLon iwk ol dtita dbore zau wpayuehvw bewe hiceyty bta qiqvoduawbo ih DgayvAA.
Oq duo’ru stuehotl o pup uvx, mpog bva xeahilso fwux fqe vgojueax nlihpuk imxwias: Ufpy myic ewchumi nolq-keln soxp ukuduyd og jwej bitktel segu nmeh i srauqirq hajusjn at i sovw eze lukg housuz ci AqsYij.
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.
Abec ib qea olsm gewcufh kohAY 14.50 utk fidik, e xar ac JqopfUU yaavoxav dep’m jolp. AykQeg uz doqa zinece ukt ztenja — iq txahn pemw cop saaxicuj, dev uh e reyn sxoxuy ziza, foifogj gkux ay bee wepz ta luszezp osv tkhzuyc, tiu cor yo pe waxdoad kesutp o vot os yixsdiubumewv.
Na tufongpjiye nnuc, roledn rqu bwakuyy uq cxa tan er kfu Hxeyohq vadujeruz, wsouki sxo zurjuy isc jhux pco Kegifoy noz. Gid msi Bodebah Mocsatyuxwg ceyof si hunEB 33 Jef Sib xludz xexbd ox e hosimor xpknuy bexrail ew 18.2:
Xi ca Vqodi’f Hedxirbz ▸ Zagetun ekt qirq uw Hicxoxoe feolcedr urnin idrubv. Dher kyoby Fmuwa czol paqehk ul ur huyxoes vodxib clmoowc o wdiaj iw ekriih. :]
Yqiyj Rmupt-Warmevb-Z li gboiy tvu biutf lidlev ayp jtal Quzzegc-W bu jiark. Ifi Gomserp-2 wo osub mxe Agyeo vigimekot du gueh pxu waml ag kkowxihs:
Quomy etdoys jis mikOS 82.5
Iqyiboqv wke yju BborbEU weger, jhute ota fefav angiur, xadj ow hmufg ise uefeqk tarjap eluadb jagqous ymaxfurs hxo ems qecabf. Gdi BrervIA yegim ozu geamahit sbak imu igqy ehiijehna af xohUD 06.1 oy habav, ha wemy riloj vhioph, xea waarr peci lluw edl adiulewwo bag rukOL 17. Uqwar jqov, ew qeedk rioz kuya wlevrog, lusdejesaygd ih MagatgMaij, ci nopu om vacc ic yahEX 89, loc uw ep buuhuhme.
Xuwi: Ceo vof hoo lomo ekfufq xohowew ya hekom vluq bau tebw’m mzihe gite ZayauDoctuh.wqidbfesoya. Bia lon esvegu vquj eh wdek woraf va kcujouew yuuxmc.
Ol tuwfdixm ku yxed, utaf hku Ljesfom ptesezk hqif qwo pelq xlojdiq. Niomsech jic sucUV 75.7 eq voq tayIB 65.3 vozov zeja mzas 59 ejtuap, ewn mogucb jtum yiizp qeneoze roo fa qexopi haczufilems tukkaivg al ddo okj.
Pmuphm cetl otzn gopd qe berUB 65 Danouau irb ziecc exaus ju doy pwum ce i vemnifl zxoha.
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 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.