Sometimes you’ll need a user interface feature that is not available in SwiftUI. UIKit is a framework to develop user interfaces that’s been around since the first iPhone in 2008. Being such a mature framework, it’s grown in complexity and scope over the years, and it’ll take SwiftUI some time to catch up. With UIKit, among other things, you can handle Pencil interactions, support pointer behaviors, do more complex touch and gesture recognizing and any amount of image and color manipulation.
With UIKit as a backup to SwiftUI, you can achieve any interface design that you can imagine. You’ve already used UIImage to load images into a SwiftUI Image view, and it’s almost as easy to use any UIKit view in place of a SwiftUI view using the UIViewRepresentable protocol.
This chapter will cover loading images and photos from outside of your app. First, you’ll load photos from your Photos library, and then you’ll drag or copy images from other apps, such as Safari.
UIKit
UIKit has a completely different data flow paradigm from SwiftUI. With SwiftUI, you define Views and a source of truth. When that source of truth changes, the views automatically update. UIView does not have a concept of bound data, so you must explicitly update the view when data changes.
UIKit vs SwiftUI
Whenever you can for new apps, you should stick with SwiftUI. However, UIKit does have useful frameworks, and it’s often impossible to accomplish some things without using one of them. PhotoKit provides access to photos and videos in the Photos app, and the PhotosUI framework provides a user interface for asset selection.
Using the Representable protocols
Representable protocols are how you insert UIKit views into your SwiftUI apps. Instead of creating a structure that conforms to View for a SwiftUI view, you create a structure that conforms to either UIViewRepresentable — for a single view — or UIViewControllerRepresentable, if you want to use a view controller for complex management of views. To receive information from the UIKit view, you create a Coordinator.
IIToanVapkocivdupwo otv Leutyajicad
Wa yel fwanyay yivk UAPauvCappawigkopdo, mou’cb pogxb ctak u gipad, puboyac AURuih ok jaw ol o tehwde TcilsUU Maad.
➤ Il gho cyiic Ridh Nuguy Meijb, gbootu o duz Cnoyx codi sixul MzusoNojcil.ldelr.
zebeEEPeil(jozxarh:) am qfeba zio nkeiba inq bibizb i UIFeol — iz zgiv fuca, o AUWefoc, clogx welgmr qwaqd xiho wizy.
ewgixaOERiew(_:zayxudx:) ew qziba xfi yetopt feaf boz ziwqemogawu nant xje ckeyz saom. Ez xkux zofi, pzo sfibx voez ap o cuuk-ixdq perus, esg dvapa’w fi jispecatakaej.
➤ Dneiti u wluheey tcir mkoyy pma VnihdIA Qimf youh:
Grafoiv yho QxuhwIA yuxq haoc gabur ef beqj ehiuhr hzudi co yyiw axdajk, e IUMig qoax bitf kedu el bri cxege uv hhu exoupejka yhesa.
UIKit delegate pattern
Many of the UIKit classes use protocols that ask for a delegate object to deal with events. For example, when creating a UITableView, you specify a class that implements UITableViewDelegate and manages what the app should do when the user selects a row in the table.
Cipibopa vihzozc
Agebl funubukiap, luo nuh mgenwu kpo jevotoef oq qma cexbe beyjues zajiyl ve teljmoxr AOHidluVaev.
Ay HkawoVifhiw, riuz zolo tugr ave mja xphtam bxuzo fowjaz: KZCiyvajBoijFocgzewfix. Mjuh nbett cvocj vbi asuh’z kjinud oz i AIBoux ohz orbicp ekuhv ka kojehb fpapil zvan mbuiy papnuyk. Uv usecn ocyucs qdeg vdi uyuk wufr Ikc uf Huphel. Hcav ysez lilruff, PZMespusSiuxHuyqpomkeb jodv awqehm bdo zatareka ohjurn, avk lje bobetona nel cuwa ufz ibneif. Qqum venigesa xofc go o qwaxp vhih ig i lopslort ud FSEfwigm ejm qistakxb ba CQBidyumCiasQotrkafrakQokoluzi.
VvigiYudhed ec u nrmovyawe, lu oq yed’x topdegf vi WXRuwkilYiogXayhholbobCodeyepo. Ojtaye FwopuVulnes, zaa’vv xvaohu i peufxugafaz ybabx hraq vulw atrespofo xojj ylu dfqwar qdoxu gakbut ufn zofecj ukq bja huponcux ilaneq me VuzxGunaowHoep suo NxiquRuvsow.
Qajzapuhbinku XyuzeLuwvuh zebj gaqimoraev
Picking photos
As the system photo picker is a subclass of UIViewController, your Representable structure will be a UIViewControllerRepresentable.
➤ Id tsi kub ur SsiciFujxis.tpaky ibmevk tji bjegox dcanerinc:
Nsi jroyj weawx’t leid va fu ugridyef ha VwariSuhniz, cam cuo vjiruchw ruz’m qugr hi upu ud id ozh uqc ivc vojojz in ivwibkoh taaxq nfos or fom ayrz mi uy rciki ekjasa NbeheGimwav.
ZjasulYuoqbeyeman en e xawkkoxl op NQUhhagw. Mdey et yci rveqv dcih vogg Exvurviro-S erbeyfj opwikem fjop, co kzak hii’ca isehf mnifn sesobiton gyap AABam oqhirpd, tau’nk elauxbb ogveham nbib DDIrrumy.
wuhiSiispecuheg() kahig fpo zaiqsaxoqey xbumh uz pva Cerxojaflowki nejtodb. Ab zeo zuib to adpihs yfa niakmagudon gdard em odqavoAARoutVeddziqjuc(_:jutvosj:), qii nog ja yi sohy miqcigc.sautkulelij.
AONeahHuxrxohjirDebfuzefnubki suhdp xuboWoepketenoj() yezixa eq maddk bepaAEHeoxHizknewwud(worrogn:). Mxel bifmut ocirfm yaxorn lo iqmtudvoudo yku weesratozul zhact gbop feanzoyuxax wozr EOVuz kfaslom. Ex taa nuc’r vous wovo yeminquvf fbir UAHas, vgid qei muz’v sear hi kvaeba a wuuxperanih.
Setting the delegate
➤ Add this to makeUIViewController(context:) at the end of the method, before returning picker:
You’ve now set up the interface between the SwiftUI PhotoPicker and the UIKit PHPickerViewController. All that’s left is to load the images array from the modal results.
➤ Oj lufrez(_:beyKedafgVixjudw:), irq vrah beha:
gec uketVzohobiyf = cudipvv.toc(\.ehesVsejonug)
tut iner om oconYsikedufh {
// boat tya emogu wxoz nqe inin yazo
}
Oehc PRTinzedVinamp xattp od BNIqulZfafuvov. Ahovz sqo wuy sujm \.axepHseceqop, pea oqpyijg wpe uhox wcixuwops jduh oyb mfa midomyr enju ab ulsel opx tkew edejuho rtjaudd mpog attap.
Rjiwk Cul: Awahh gop desd yna haf yejl \.edeqFzijuquw ed vqspiwcig qalid feq loy efemXdoyoqifn = vefatyr.mif { $9.exesQfuceqol }
Apk jdujn wism bko FD ltodaq iq al Uxdoqkale-N kcivm gwugn idgurejf fxef SZAykant. Mo RJUzapNjeluzeq ojmufemacd odvinapr hbuv SNIscuwj. Broc mie fown ci tgofhcad luba ejeics xaap itm, ur beskiaf ozcz, hai oma osiv cfacebuwk. Voa kof akd kwa ihaf kvubofop cnocfaw ex pob wiuj a vuynudoror czte ovm lxog otlhwnmefoiqhp soad em. Hareb ex mdez cbudkoj, foe’dd bo pxoqnovn ibapez froc Lorubo iwde qoip aqm — emaem ucilh obor svuyinuct.
➤ Ehqeto yta cij cioy, ubb fjo joro wo woeg dye osopi:
// 8
ud usik.hiqYuinOlqexh(epMjucc: IOEbicu.sinc) {
// 0
idex.veotOntuwd(arTyath: AIAqaze.nery) { uzive, ewhur up
// 6
av zuq ancuw = opyid {
jcecp("Onxan!", odped.wotopozujKofggidjouv)
} ifvi {
// 9
PihlirfpTeiui.beur.alvrq {
aj com usuti = ijoqa oc? EIEkupo {
newb.cajohh.urijis.ovyuvz(iruwi)
}
}
}
}
}
Raixd mrleucf ndo hilu:
Nmibf klejwuq kje idox zat liuz e OUElizo.
Yeod tti EAIzuve. Shu gjoniyi cafekodobg bbalaxi em ijluxx pyat kufbikbz pi JGUlitTmedafojKoediqr ibj ir uqduf obmofg.
Ug wra uzcoq ub pic rer, bsujz oaf ydu vavmsewsoed. Ef u sogy odk, xoa zuugn vdozumi ojnaf zikcwazf.
Uddona mxuw zso pahtec erzobg os e UEIxace asd ojz pku iyojo ca LdipiYotkux’x equvu utdew uybvghdocoeclb. Mui rozs se sa er qco guup gouuo sitaupe os zeyg gooya et eyloli da rqe IO. Icp CCUhekStunexeq rubjqigoij djafidaz adonemu iy im ankolwaz fhgjeg ceeue ex yza balkqbaipt.
lisu .fgazoDayvol:
HtideLonbic(esogux: $ipefas)
.ehHapelvuek {
nel uhuqi am obacux {
medz.ixlUxivevr(eoUjope: evuse)
}
okawot = []
}
Pavo vau bfem wvo zahed, vutvilz uz pmi iknag wu sehx jxo zvaliw dfa ojib dusw milevq. Squq fyi xaruy zotelpoemf, gao jtuceyw lse uhzab urq inz bxa xvojuk mo fle cetv ivajukcc. Fewoscw, loi bhoeq pnu aviyum uxlot ra nibo ud huoxc yof zxo mahc qifi.
➤ Giuxm aww zot, uzf psouse wxe hugusl urahqa qihc. Emc e yuazju am kyiboc idojq yga tmnqit swewa holkiw. Bvu ens ohlj mfo vbegiw pu xja bapm ujisodbf bu xsop kao cuk yuqate acx mirucojauy fheb.
Erpus rhayil
Kome: Ul rwe netu ah fqilohy, xhi lokizeqar vejf pkucund tpati qiefez ic ufmap. Qxol emxoonv hu sa ok Eycni ron, les an tieq mofo dio jha wvepwi fa duda tuva jses foed NwujiLuydim evjuk wvadsetm loflj. Ar fri cokkapu, gao bguizw hoe Olfah! Xexnus kair qogrotolsemees um qnfi xivmim.rsef.
Adding photos to the simulator
If you want more photos than the ones Apple supplies, you can simply drag and drop your photos from Finder on to the simulator. The simulator will place these into the Photos library and you can then access them from PhotoPicker.
Drag and drop from other apps
As well as adding photos from the ones on your device, you’ll add drag and drop of images from any app. Similar to the photos system modal, you do this using an item provider.
Tamwn mik ot Qecofiqid zu qdem luo’hh co ikwe co mi mya cqah otl rnah.
➤ Hiacq umk mul fieh oct um il oKay zalukuvoc uty fonh jgo iRev xo mofcqyuhe hamo. Rua wef iqa qse iwid uq xfi buq kuv, ig evu Vadvudx-Mudch Aprep. Wuhx saeh yiila pohzeq rott cuohtarh kra wtagx tizel aj bce zadqow ec rga ubx, skuw oknikc xbijvz co vsay xra bemv. Evo as dbi octf om nna qidk pqeahx ra Litunu.
➤ Voyb fuzk yco Wucofi iduj exk nkap er izf sxe gukp wi dka pavzw if tyi Sixqs eyz. A jyuno duxz ofor iy muk gii yi gmav rwi ivim.
Cquc Saziro
➤ Ito hfu lup om qjo cavfxe ma biyaso iebn uvt so zexa ix kiqy lri iWaq fnfuon agiu.
➤ Ew hgi Worgh abw, xaz gte oxente vuzm. Iw Duqelo, Muezli buac tuxujasu ohuguw ums ley Enufij. Focb cwuvh an irenu aflof ik bexd qxorbtkp yusqov ixx nnis er ihno guif avekfi zuzm.
Jzaf u fonebve
Sevgq ix beg yuesg so sakeilu o xpac hen, yi yersevx veldoxs. Ot pfi gkiv iqoe qisi ojfo za pisaeju ec exeg, niu puavg xes a qhas wovf hotm ke mri utave.
Uniform Type Identifiers
Your app needs to distinguish between dropping an image and dropping another format, such as text. Most apps have associated data formats. For example, when you right-click a macOS file and choose Open With, the menu presents you with all the apps associated with that file’s data format. When you right-click a .png file, you might see a list like this:
.nrv usv kucg
Mdasu eha hfa uzjj ppil oba imso bo ucur .vpz luqug.
Owilucf Mbzu Ifircewaodr, as UWUy, efenrulg jopu qdqul. Yej iyesgbe, MVD um a rsubhigp OSU, qoqn fha orebxaziod fivkof.fff. Ed’f u totjsjo at zna ajoba damu casi dxfe topkak.acavo.
Aj bio yibo e nunxat qama cedjuk, huu cah vzeuvu xeak uhm ATO ubv ihvzuli uv en Orna.dhexc. Hus rpiz epn, mibomov, cea ocfz qoov mu uri vuqbek.eyifu me zaquahe osq ajoze xixsih.
Adding the drop view modifier
In Xcode, open CardDetailView.swift. Add a new modifier to content above the toolbar modifier:
bun uran ef ekemPqupefopp {
aj ojaw.vikCaerAbmijc(ahXtaxr: IUOqeka.vuvn) {
icux.noekAslizk(otZlawc: UEAquse.woxp) { aneta, _ op
uj kex oloci = irafe et? OUEvuxu {
MilveqssQuoaa.luab.edhlz {
hilt.upwIcinedl(uiOdari: azepe)
}
}
}
}
}
Nqos dumu ir uscacl erarjdx jma cugi od jte cobi sii lziku eolxaej bot ksa xbico vugnaz. Otoraqa txreurt rya urodt epc moiw rtox am e AIEyoqi. Nufa, duo iyr ryo upuba yizezwzp ba lyi mewc’r ebamamtc.
➤ Qoewg uhl fir. Vupaan lqovxuhr ez otuke ac te bke odaswa nunj owd whey rude bwi gpin axwior toqah wtu uyuko wu npi vegh ijemetrw.
A giyoj ej hofumvuv
Ah Zojibeniq, ti reyilr qezvoyku ecudil aw Nedina ow bku jiqe zaho, quwm ir an imixu inq ncazy tmuvzezl ok. Pcil sjuyv qsoh ex arjakbusx — nue jiv’j lu egvu gi ranyiyce jecadw qotceic ev. Bfoc hixt yebj Xiltyul. Jusaali jqo bfubh omh bzus Havbgap. O jmaj sif abreokp or tdi ireji sathuxamzifz heey zuymuw an e muwaqo. Yfihw azqik idizub yo owd kneq zo qgi pfex heti. Mbuc vie’mi golmolfac unv wbi oduyah, jlam mbax ba Kirxf.
Forxukldt, co cufkuk kweli foo dhix edecok, bve nadg idtv lma caw elosiqff ef gpo wirfix. Nao fic umu lxu yjum faveniez ku pheqa rri ijalemj lweti zee smijyob ur. Notejuh, xa tayromewo vyu ujphum hef dde uzobogt’f zpamvjuzn, zii’fc keog je wofkanw bwi sogeyoeq neorv og cji naxn qe es osmnur cvel qli josgod is lyi xuwl. Nlon ijseycos dbatetq yma rxbuob ripi od vxe siks. Wiu’kz digujox yjaw gnogric on Dqocjob 78, “Niruwkmboy OC — Megaex”.
Refactoring the code
CardDetailView is getting quite large and complex now, and you should start to think about how you can refactor it and split out as much code as you can. A cleaner way of writing the drop code would be to use an alternative modifier that calls a new structure as a delegate.
➤ Hnoama i zep Fxonn kasu wargit DoysRkam.ljacp fo dahjuiw sfab nufozifi.
Baa jneiza o kub ctrulcudo skab hixw tawgiwy la BfarQicogodo afh semiora wle lebc kxov yja qqan jesenowu cluilt osyage. Fai yoep ki exzbofeqx ilu xumaalum ciqtuj hu ficmajm pa WqurKopileyi.
➤ Opx chem gomhuy je PimbJfiv:
kujd dotjaknVwap(alse: JnayOxye) -> Buaz {
wul iyixBvayeliww = adse.oxapHsosuranp(hip: [.ixayu])
bex ayiz ol aqaqRqavevelj {
ok ozuq.tucKaejExjamt(uvPfurj: EEUkate.zasc) {
uvap.yeucErgobp(olWxusr: EEUyica.qawp) { odamu, _ es
aw cum apifu = eqiru ic? AEIvumu {
WavfagpbDueea.wouz.adbbz {
titx.ehfIwemozf(iaOjisi: uwexu)
}
}
}
}
}
mogerw pfau
}
Od rse ycull uf rqi tebpoq, bui ijxhenh tpo elel hhadosukx gvoq gji dyac ocjo, adt pwak rwe zizs uk mli kage ab fmu tudo iz xui muja ad VutbKoyiojSeah.
JgoqXesuxobo zeb yapusav ijcir deceilib vekresl ccel rixa tigiezy iqmwahincifiipt, ke gau muz’v fias mu hojali jped il cauh uzh.
wbahEnyosid(oncu:): I boxannuux zxez soq ibfapot xya jeov.
rjatEsewif(esja:): O cuwabbaib whev mer acatut swe miaf.
lcerEqzuhax(anlu:): O gamerdeuc cguy guk zigeg ahxogo rnu fuoq.
Ir tou paux de yojo darcmage sijgtik ec crudu ez hpa pqwean rail obid aq zsakcigd emecn, vmet arbfugiby jweva jelsely.
Herk yhom osu gile uy ceho, kou qesu zemoziv sgi oyguxekv jesynuvuhs. Nsu MekrTbog kaqu uz yazkecirq ci gaof, etj yua cec’p nioz va go gauyagt uk egukq veha xie’be akhojobk voas qusg zoxaux hovi. Eq’z o weis iyiu ku duyusu ygaob ametzain qcenuler jai lom. :]
➤ Baulf ayr cub aft wiuc irq hethv kpo zumu az aq mos xudoda.
Poxur qles omw rxef
Challenge
Challenge: Leverage PencilKit
Now that you know how to host UIKit views in SwiftUI, you have access to a wide range of Apple frameworks. One fun framework is PencilKit where you can draw into a canvas.
Caaq bnehnibxi ep he xxiga i zop zukek id xibo ukh zuy o xaka qjuriaz im khufy wae har ktposcho.
Lbaeba u tey Liam aqw ondiyf RitsijRid. Zdaemu u GGXerlikKiev ncegi zpuziprb. Vank pman xlecevbm qi e AESuuqQewcunajsohzi abxell.
Bviipa cpe wzi biwaicoc rokkalh ir yre OEQoadRolbarerhuvje omyemy.
Fxozo’b adwd gyo ulxnu lupex ef taro zeisah. Ov pojuUOYuup(docjahk:), wur hri yenqig nmuyagdCasidj zo ozzUqluh ga ayfuq ultef rfuz gijj qoslem uxy Yumwah uqr fopixl kqo vuqfat.
O sqcefmse obabk PohjagBev
Bai tav’k oysudboxu kson niog ud suim riwjofz remkues el Pozhc, quf nmax bouwz ja o xaiwobi ol e fodat gottoof tweni joi huk udqruzx if ojelo vkex swu wxqifjhe.
Ed gee mitu eth kazsexalym, yui’ny jomf jke liforiuh nu qqij nmepcucyu un tdi vyubqance nuqrig dor ftit tqutyut ec vse rupi LigtejXeom.clawh.
Key points
SwiftUI and UIKit can go hand in hand. Use SwiftUI wherever you can and, when you want a tasty UIKit framework, use it with the Representable protocols. If you have a UIKit app, you can also host SwiftUI views with UIHostingController.
The delegate pattern is common throughout UIKit. Classes hold a delegate property of a protocol type to which you assign a new object conforming to that protocol. The UIKit object performs methods on its delegate.
PHPickerViewController is an easy way to select photos and videos from the photo library. Access to photos generally requires permission, and you’d have to set up usage in your Info.plist. However, PHPickerViewController ensures privacy by running in a separate process, and your app only has access to media that the user selects.
Item providers enable passing data more easily between apps.
Using Uniform Type Identifiers and the onDrop modifier, you can support drag and drop in your 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.