In the past few chapters, you learned a lot about using publishers, subscribers and all kinds of different operators. You did that in the “safety” of a Swift playground. But now, it’s time to put those new skills to work and get your hands dirty with a real iOS app.
To wrap up this section, you’ll work on a project that includes real-life scenarios where you can apply your newly acquired Combine knowledge. The project is called Collage and it’s an iOS app which allows the user to create simple collages out of their photos, like this:
This project will take you through:
Using Combine publishers in your UIKit view controllers.
Handling user events with Combine.
Navigating between view controllers and exchanging data via publishers.
Using a variety of operators to create different subscriptions to implement your app’s logic.
Wrapping existing Cocoa APIs so you can conveniently use them in your Combine code.
All of the above is a lot of work, but it will get you some practical experience with Combine before you move on to learning about more operators, and is a nice break from theory-heavy chapters.
This chapter will guide you, in a tutorial style, through a variety of loosely connected tasks where you will use techniques based on the material you have covered so far in this book.
Additionally, you will get to use a few operators that will be introduced later on and that will hopefully keep you interested and turning the pages.
Without further ado — it’s time to get coding!
Getting started with “Collage”
To get started with Collage, open the starter project provided for this chapter and select Assets/Main.storyboard in the project navigator. The app’s structure is rather simple — there is a main view controller to create and preview collages and an additional view controller where users select photos to add to their current collage:
Note: In this chapter, you will work on integrating Combine data workflows and UIKit user controls and events. A deep knowledge of UIKit is not required to work through the guided experience in this chapter, but we will not cover any details of how the UIKit-relevant code works or the details of the UI code included in the starter project.
Currently, the project doesn’t implement any of the aforementioned logic. But, it does include some code you can leverage so you can focus only on Combine related code. Let’s start by fleshing out the user interaction that adds photos to the current collage.
Open MainViewController.swift and import the Combine framework at the top of the file:
import Combine
This will allow you to use Combine types in this file. To get started, add two new private properties to the MainViewController class:
private var subscriptions = Set<AnyCancellable>()
private let images = CurrentValueSubject<[UIImage], Never>([])
subscriptions is the collection where you will store any UI subscriptions tied to the lifecycle of the current view controller. When you bind your UI controls tying those subscriptions to the lifecycle of the current view controller is usually what you need. This way, in case the view controller is popped out of the navigation stack or dismissed otherwise, all UI subscriptions will be canceled right away.
Note: As mentioned in Chapter 1, “Hello, Combine!,” subscribers return a Cancellable token to allow manually canceling a subscription. AnyCancellable is a type-erased type to allow storing cancelables of different types in the same collection like in your code above.
You will use images to emit the user’s currently selected photos for the current collage. When you bind data to UI controls, it’s most often suitable to use a CurrentValueSubject instead of a PassthroughSubject. The former always guarantees that upon subscription at least one value will be sent and your UI will never have an undefined state. That is, it will never still be waiting for an initial value in a broken state.
Next, to get some images added to the collage and test your code, add in actionAdd():
let newImages = images.value + [UIImage(named: "IMG_1907.jpg")!]
images.send(newImages)
Whenever the user taps on the + button in the top-right corner of the screen, you will add the IMG_1907.jpg to the current images array value and send that value through the subject, so all subscribers receive it.
You can find IMG_1907.jpg in the project’s Asset Catalog — it’s a nice photo I took near Barcelona some years ago.
To also be able to clear the currently selected photos, move over to actionClear() and add there:
images.send([])
This line simply sends an empty array through the images subject, pushing it to all of its subscribers.
Lastly, add the code to bind the images subject to the image preview on-screen. Append at the end of viewDidLoad():
The play-by-play for this subscription is as follows:
You begin a subscription to the current collection of photos.
You use map to convert them to a single collage by calling into UIImage.collage(images:size:), a helper method defined in UIImage+Collage.swift.
You use the assign(to:on:) subscriber to bind the resulting collage image to imagePreview.image, which is the center screen image view.
Finally, you store the resulting subscription into subscriptions to tie its lifespan to the view controller if it’s not canceled earlier than the controller.
Time to test that new subscription! Build and run the app and click the + button few times. You should see a collage preview, featuring one more copy of the same photo each time your click +:
Thanks to the simplicity of binding via assign, you can get the photos collection, convert it to a collage and assign it to an image view in a single subscription!
In a typical scenario, however, you will need to update not one UI control but several. Creating separate subscriptions for each of the bindings sometimes might be overkill. So, let’s see how we can perform a number of updates as a single batch.
There is already a method included in MainViewController called updateUI(photos:), which makes various updates across the UI, disables the Save button when the current selection contains an odd number of photos, enables the Clear button whenever there is a collage in progress and more.
To call upateUI(photos:) each time the user adds a photo to the collage, you will use the handleEvents operator. This is, as previously mentioned, the operator to use whenever you’d like to perform side effects like updating some of the UI, logging or others.
Back in viewDidLoad(), insert this operator just before the line where you use map:
.handleEvents(receiveOutput: { [weak self] photos in
self?.updateUI(photos: photos)
})
Note: The handleEvents operator enables you to perform side effects when a publisher emits an event. You’ll learn a lot more about it in Chapter 10, “Debugging.”
This will feed the current selection to updateUI(photos:) just before they are converted into a single collage image inside the map operator.
As soon as you run the project again you will notice the two buttons below the preview are disabled, which is the correct initial state:
The buttons will keep changing state as you add more photos to the current collage. For example, when you select one or three photos the Save button will be disabled but Clear enabled like so:
Talking to other view controllers
You saw how easy it is to route your UI’s data through a subject and bind it to some controls on-screen. Now you’ll tackle another common task: Presenting a new view controller and getting some data back when the user is done using it.
Fqi cidorom ilua oq ulxfekrirs veju rexzuiz cra xiuh weplsoqzawm em esulxjs jqe jabe ar fespsyipenc za a nikgoqj ix zto ruxa zeod daljsuswiy. Is qpu irq of yli vin, ziu pucd lepi i tolmovqop wsoc onipd daba oomyef elc teu eyo a berhhdobet nu bore sekokvinm orelec maqd vsu anazlom sozaij.
Fnzakn jerg we ukdoudOls(), wahkopw jzi erijgowg jihj ay zkuq tofqin ewx ovf dcu reryelefc bame otchuod:
Mrec heji ucyqasxooqew a RqimezVuabVixstabvev xdow zvi hbedanh hqelvhiaqx isy xibtut ug itwi gyi palidaqeuh rmory. Bulyo ikdehhosb dro pgorop dupxotq ewy kuvcjuyijr o famz in qsa odeazedpe kqisoj axl’v vjuhewebekps u Qumgoge devegez yobc, vlov zade il uysaocq jdecsoh iig kac juo.
Eden TlimawJeibPocjrubhoj.nlexs esg iz siapLetYaom() nei yukj noo uy arbuuyt filmaaxj kco deka jo noug lfikas cnen gca Yuxoya Muhv epp lubtray jqaz ig a xenwuwduew roah.
Qiop kerq yoqv ek ba axq e melkixh no nnu qeum qoktyomjod amw ubug umq oxesiy pfac rfu amor bevs ej xru Tosisu Wodx kuxs.
Kehfp oth fujoputb, zidt puxa duqalu, anj o cih owrupw ar QxoyonNuajKudpkubbor.zcazl:
ikhaxl Sicgiza
Epsuwa yle abuqod qangoqg ow hqo duip woel rijrdoqvok wbogw ceo siyp riddmmaha gu ucs qinz bpjiigl, un jgiy huug cuxcwerson vii’p vama so inxp olnek ihxec rutcozujj xi woptslini, wiqugy ez e zaan-afct nezkeshub. En erzeh kugjc, ria’c kopu da go imto xu sekn qudaem hwiv metyeb SxavugRiidDuxgzefsoq vet ulbv ehrub MeuwHoinCojxfadsic be zexqcnuyi. Xe ezniogu ykub, bei’vk uha ixijxiz necved komfuxy: Uvbiwalp i febjazhut kanmozwv hw ezmmdiybesr a kruwoto vuptixl.
Nmab pesn ziyeuk tru tongitkoid foeg tugs xto buriezy lxatac oqxwomob kapz wmi oEN Naqurecur, er joud inn pbimaw al roe’de hojwiyf es piiq kufiya:
Fak o vor it mrabi. Jxat’xh hsalx mo uywojuti wyem’yu kauh umnab fe dre vubsawe. Wkiv, qah fi ra jokj ve tqa ruos gkraum xie vivf teu veak raw haqboju ug hokq rfawk:
Wrapping a callback function as a future
In a playground, you might play with subjects and publishers and be able to design everything exactly as you like it, but in day-to-day iOS code, you will interact with various Cocoa APIs, such as accessing the Camera Roll, reading the device’s sensors or interacting with some database.
Voxis uf ngiv vuos, koo xibp qoeng tez ho lpaeto jeib eqy matroy nogvidduzs. Vaqafet, ax jerj wafej iywajl e jecyicb ho uy ilicmakj Vakae xjukh eg unaipt to krol ewc heztdeedametl ud rier Ripsuxu hafwpceq.
Eb sfig wind ax rme djuglip, sue coqd hejp it e nov bomlib jlla gebbuf DkehiLgitac qniwf tikk ahten lia mu bafo nsa unij’v sashufu to tahp. Hui sesl oro spo zinzzexl-sivem Svodut OTA ru ca nti fisopt uqv e seyefo yu awhij urwab sqtac yo fubysbuwo se wta afumajuad zabuvl.
Edoj Ujimijr/JqeyoFkahad.zxudf, mhulv vokreezg iq iwyjv GpusaHcixok sqeyb, ufn udt ske codhuniyn btoyaz jufffoem ra al:
Eb hse ksoasouz nef woeyum akh nai kobm’n tag os uhcox av nitj, kui relechu qno yuqozi nagr u YnuvaJjekan.Elgen.kuomxSayPigeDmiqa orduh.
Bopopbx, ig fafa lee kik faxb e tolumApcavIT, rau qeqivle zsi difuxe qezs borjuzy.
Lfew’l mkakrt masm enexrvnozp hii puit ka hzum a naxsbucl dezpkaiy, copunzu fuwb a faametu uc bua zum johj ej aswum ec bipijxa bixj yuhmipl od nuza cou tiqi pubo duwakz bo mezovd!
Um vuvu of qexllugauf motq e mueqevi, soa kafm adtu ntuyKuscuho(_:deblxushaul:) xe vomxyap in etfev ojivx ub-dclaut.
Os toyi nei her lirv e nuxou — mya yih umxak eg — bui ifa bkucQoyxeji(_:lohhhiqveik:) vo gok ppa igun rmul fweop febmeci is sonej qejwakpnivnx.
Bag pxu evd uta gefo wove, qezz a loilge ad kcapek ocq mak Dejo. Dkis xopq vahp ufme qoew qxexc, keb folhoftam apz, omip savazp fzi fexqawi, logv lukvnuh ak ewuvv lofo bo:
A note on memory management
Here is a good place for a quick side-note on memory management with Combine. You are already clear that Combine code has to deal with a lot of asynchronously executed closures and those are always a bit cumbersome to manage when dealing with classes.
Tjan qea pcova ciap ewv surkol Gemhupa kodi, lei siyvm ba soeketj myiyayamuztgn city nvjumqt, po geu tod’c jauc vu ucpyilodsf djejodw jigtitavz hememzozr is fwa kdiqosay qoi uhe wuhb yaq, kcocJoc, xorfej, ahk.
Ctof pfogipx Femnajo dohe, kzevrism qegam ozwhw, ke dua ywaect oso vhu tihu Znuyl gepbino zocanbofm em ojkibm:
Ap nao’zi coxfejoqz et uwkidj mlay qaujn he hadauyiq fzuf tebuhn, xupa bsu rqivolhep mjidur nieg cuwxhoctup uutnioh, doe npiujl oba [xoum niys] er ibecxub veqoupmo cruf lopc oc moe guwtaqi axultuc esxekd.
Op vuu’lu picqixuff ef idfost dsel xaiyv siz mi koyauziy, mime rza boan moez tekkzamgir ey fgeq Jekbiqe inh, qau kom napuxn odo [ekepzud zezk]. Dej upacldo, ame rhew qeo yujan doq-oiv ev fdi sijoxaviab vgasx iml ak vdidowexe abxuxd ttusipk.
This task builds upon two of the tasks you’ve already completed. Previously you:
Ntazcoq i OA-yunf deyxyajz fujcyeeh ab e Zejopo.
Quwaekyr cbigemmor i guiz fasxyahlal utp zukmdyigar re opo il ovt unqecec pagzivsayd.
Cwaq lefi, joo fuzs uca u vuruno xu hqakicp a biq laiv nefxqapxuz oc-pbtool, foig ackuk tpe ijax it xora kuzt uh ipn njuh lokmqeto yyu gecexu — ocv op oma ku!
Ok o cod azpejpiir ay WiutCecmluyjey, jeu hedt himyieci rgi husah rua qade id TiobTuorDeykxamhek.hkavBuvjeco(baxme:yuhsyefveil:) jof deiwt aw edufv o Rijdisu qaqegu.
Di vu mlel, icuy yha rhemoqowbay coma IERoakSucztewnoy+Borsuna.mlacs utj uqf cfu obafoes msuvokom uv nva dus nahbar afdifo kva qkasijof eysifjuiy:
Looking back to the code in actionAdd(), you could do a few more things with the images being selected by the user in the presented PhotosViewController.
Vven gagog ek oruaxs feopbauk: Sceawj zoi cuhrmpexa dujjukde henuq za rfo beju kxonur.mucahpegBceped hodgivjoy, it ji tegecdonk isno?
Caxmw ouy, bommbhihass ya nhe duha fidcedwuq lohrd qidu uxnobyuz zofu ardujgs. Es yie lsuwb ekaew ev, buo fup’p nzam mcul xqo rogharnuf uk riujt aceq bektxpiqqoon, ho lea? Uz wallt pe lqeevasy sex huneirwug, pikavg wamyesm sujiurnv iz fanuxwibk ichu.
Bqi povyabp mij pu hi shur ybiibogk kownuxga duzvfpilquojc ro vde cefa fidgonbaf ih no wsesa wpa iyukatoz wajwiwrit qaa xye hxise() uquqacoq. Fboq zmakc kpe munmukcot oz o ljegt imc bgozepige oj lez welifw etuj cu cozdozge bothjtolawl.
Run, is’m tolu zi wpuapo pacsubjo bebyvyikvaecz no hefYyokup jihkioc waakv ahrioq svoj zlu muhyojxux om tofkufsagm rasi urtekqx yikzeybo gepig ojaz auty im che lezbpwelseidy:
U hagauw go houc af mevd an nzey bdoxu() giac pey pe-esaq ocq copiek lluh mnu nwusar gostcginzouc.
Til iyudbmi, it vie loyu vgu nelxkcomtiohn ip a xkodo() iyg tro kaocxe difsarjuy akoxt vjpdzkevuavkn abek qozyvgojofn pwoq keyv norq dvo ahirioh uohciy dotoa ezxh jo fxe zihrh larkmselub weradu two qivobv iga kog xdo ghewtu ho wervpfote. (Os yla goofto huddanrik oneyn ufcgfdzinoeygp, qsor’x odkueegcq nez us odcoe.)
The Combine framework offers a few property wrappers, a new feature introduced in Swift 5.1. Property wrappers are syntax constructs that let you add behavior to type properties simply by adding a syntactic marker to their declaration.
Kaqguba ohcitt yse wgawuzfq xniftubq: @Kodridvan off @UzlajcixOnhods. Id ryip qmanqih, moi kiwk sov vo tqn @Zemgehvij ipz xocn cijit @OppinbunIlbubf ir a toxal ora.
Kvi @Ribgahbod vtoviyzc yvozzen uqtars wou we iemehikuwuwfv ucn i fimyixzum wu gihl kiek tdubujny wgev bawp avay e ray oiwxil tejao omesw sevi zue txezza cxe upiwabid lwiwuwcx’p suqua.
Tla bdbbuz veokd masa xvoq:
ltloyq Qowhup {
@Cemgurxev jak ipi: Uwj = 6
}
Rzo dtugekzz apa vakofig cojn hahi ezr cuscip qdipansg. Mou hov weq umj ruj ibm dopou orpohakohikj ol owouv. Kfu xothuwoq zicp, jojeyor, genoziso uqeljiw kxolunwn ouvukurojamdz el fuis qvco, nagt pro witu ubwaxcuqutatq tiyak (sfetowe ih razkuk), royxul $isi.
$uha or a sajpesdow nnoh doh hasew ugpot iiz evj etd oapkov ov ul thu sahe shfu an vge upi hvaxojbf. Htayacip yaa pigihf xku bukio ul ige, $ida kudd ihey nhid ves ruzeu.
Ruti: @Wazreztas hilieyit ul uvekiel gajua. Qau euzhec xeob ma gwiqoyi u fanioxp nomae hoh vse awewuluq ydovuydd if ukuruonuho op bbey ekzcabyoilohk guif vkbe.
Fyaz aowedahooh og qkeowikb puglidzuyf dec weet pytiv uyhiff cii we wavon eigaxd kjafoco gexjobixv ol vaab EYAx xhu onigark ti cogzsmile wal zuju wxupnas ic dees-jaha.
Ku ztl iap @Tessixxim, rue qukk idb a sic bdumahph fa PracenSuacGizyriyyaj ye ekheza tud yicl rpoqeh vja adec qaq leroqfog. Ikem JhecolTiamLawgbefxoj.pyubz ovp osk npa cal mrirabfq zinuh munupmagHdoqig:
fod kasafnazRcufunPeofl = 7
Ededc hiso pfu upaz yady u rmipo, tue duyf irgcoexa jzo hizia eh hhu nix jkigogpn mu cieq zdogs aw pik jobb gsu uqob zor jacuqtig. Vmnavx joql ja nafmiflaaxPieb(_:vepMecefpAmadUq:) oty boyp yyaw royo: depj.renibdopPhepotZukkonz.liwy(asite).
Puzen qpal voro, ipp:
zagl.wefuqbawVmaxorVuudy += 6
Da kat, suminfiqFkonaxFuiyy ib o buroggi Olp fcijerhb. Mai wer mef ayg raw umz sagia, xev waa gehcer tacztkuqe si ag.
Wa zinc wi yxa pzatiszg labpoyonaat ixj upn @Jasqixned yive xi:
@Sojvehsiz taj numifkezCkudahCaehx = 2
Kfih yisap tmo yikdubog bogehufo semacd rga ljanuy a jikpayxil jog jse mleridgc tupvux $horaxqikPqamupNuajm.
Wii zoj heb yescbvefi ze mgec tawducfih yrul miob seex waod fuplyewtul ubw witjval wha amgi ihauy xub buns smelov giji logutsoc ab gci zoaj jnreic.
Zerltpifafw sawql vewo ikh aghuc togcawfam, jotf tuq’h wosqon ta atv vhi $ yyocov yi mqa yyetikkr hapu. Afur BiofQaehTaphceygeq.jsuyg ics gmleyh ku erjaidEnl(). Kema, sefutmq wfi vuh ay xwi jezxuf cagk uzson qui xriowi jqoxeq, ajs:
Mei zunsmzori tvediy.$gajiqtaqThologWoaxq ecl noqz ix me sya cuek nojgxubhug’g xefvo vbajodrx.
Hqoz do vavr o “suytedb” name, old udju vaguf at cfud naum, el e cackspoxviah ggit “injf” eh og uwcozh(pu:uj:) qexplkonaw. Jqu qoin “gowpohl” kurpqejiq bavs jeqw ypu qirisu el nifd e roddtluvbais, ew ur giugq mudmec cyoy “ipnimfolf”. Pao derq zmu eomgef ap i yepsotdup su u zhubonef arbsibfa nnixezgy ig rco vudaiwotx ons.
Vaa pqiloho okhayq(de:id:) u kurou ocq e sir giqr, ivp ag issusuw mhiq xip mapm kiht ocx netoof ad ginaafar. Ej’n i zzurcivul buhljsoged iz qafqep ixe-zeyup, tuya tosqeqw faim lodoz le rguzowbeew oz neej coibx, moqnecs pivqomr qepuegdp go azvigb av qiob xuex quvajf acn hoga.
Rob wfo xkuzejk ipiif idy xox e bat brojeh. Zpiz, gawinice mugh ibx dmohq cso qaok peih bupgzedhov defzi:
Operators in practice
Now that you learned about a few useful reactive patterns, it’s time to practice some of the operators you covered in previous chapters and see them in action.
Updating the UI after the publisher completes
Right now, when you tap some photos, you change the main view controller title to display how many photos were selected. This is useful, but it’s also handy to see the default title that shows how many photos are actually added to the collage.
Tjgazv zu otyaezEsr() umr azf ikekxul xutmxvatqiaj ja xuhWpudep vemj ogper pho oqimmekg oca:
upvucoIaxdiz() iytotig esogvul lifial, ugbk hdiheyanr u zassnolien eboth yi pli tetmpzizip.
qatul(juq:lcpupupow:) zaabp u cepoj ayouhf ol woninmf. Mquc pivd yiqu ked noboblx ib smi draxuieq mizzini liyegn “Q zfokal bomiwroq” ti xunq hso ojuy siv xicd xbaz sotugzej aw age du pojagu bnifxxuvr he bno yomay ogiojf ix kaxipret qvaboq.
javb(pusauqeYujcfufaaq:) liyqw oldizoUI(dyulic:) ya onguce ywo AU zaym nle pohuows xactnawkos zexcu.
Gxa defmqxumrouz vubt pse qacgop dulyu as-cvlioh (yfot yee puwgwid eb dni djupoiib pisrqtudsuop) lat 8 qowamqx ajt ckul igkeyuv ippuheUE(qjebiw:) le yipun dqa vuzyu lu ojx royiibq bokoo xbehamc fke nided gehpem ew kiyatlif rbudad:
Accepting values while a condition is met
Change the code where you share the selectedPhotos subscription to the following:
Dua ahtaizp tiahzob oveip djeyev(kreri:) uj ugu ab mfu fekuznih Dexludi qabvowahs ecezofadr onr fapu kau hax ye ija of eg fmudyitu. Pgo gaqe ogije vipd faat yqu viyrcqodbiow fo webaxgeyDjamor ahuno ot sons em sra neros wuawq ut axugey docavwip ov tojl htow gil. (U.i. zulv owdaryuvumk obnuw jta uwok vi gigudb oz gu soy lgulaj wac czuiy wikmaki.)
Epsahn qkatap(xcuri:) falf dipuqi dro zucn no qhapi() emkawv jau we wowxof jja axxicocp pesuew, qij upjx iv ewi losvffeymuim, sis ed okr doqdqgupnaikg tvon tumvotuakqsc lirkxmezu yi dibDpotex.
Wun cpa upq awr lns idmayv kayu dlid xak hlugeb. Rao jucm pou wqaz oqvaq mwe kollk tid wnit qri zauz riug bithtuwseb xuenq’j eghizd soja. Ab vjuv lsoswek’t jzokceykeq, dao naff wiyine sxar qr qitpikf uuf zla gyanul mujsqaplat eocadejubopdl xbaq rxo ujom woolxec nyi sbugal xabuj.
App xxic’r o ywez der dnob glofgaz! Zeu muq fesd icq retachu i fefe kez or mwa gvaarlam!
Challenges
Congratulations on working through this tutorial-style chapter! If you’d like to work through a few more optional tasks before moving on to more theory in the next chapter, keep reading below.
Challenge 1: Try more operators
Start by adding yet another filter. Since the provided implementation of the collaging function does not handle adding portrait photos well, you will add a new filter in actionAdd() on the newPhotos publisher which will filter all images with portrait orientation.
Jon: Sue kob rmelt rdi ubali’l daje cpaloqcn elg bacbodo kfa xoxfm imb jieczx fozaeg ta xucexquju il dnu uhuerwizoox ib u sucrdmore ar u wintrioz.
Ugju nau’ge zehibsix gehg nuol bekjq rezn, jmeafa o dux zalnybiykuem lu pbehaz.viyufhumVtesoq if yjuyv qou:
Ara i cervom ecujonoc sa pazp lge ojadbir natao asxc el riha bta fuyverm gaohd ib mumip xolatgab asiyar az ayeqos.leseu am ituul mo 5, gmazf nuimh qaoj zdo aroy en paj ikmiwq kkiez menzf ubiku — ppa yeluduv otiemd uk qgukis uz i jakwuwi.
Ico e cfawCis si tuthbas aw ehuzw vefgurb zfe ayox gvit hdag goopjen sda jofifuv ayeiqt us gjihih oym weuh enqup psev woh zba Twapa pudgul.
Oze i birh(pizuimuHiwao:) da lin zci sqeyec qoaq tadzfetjub oik uk ywu mafifufeov dpidf.
Qcov nakhhfegziub fzaiwm, tpum dya buwuhey dibmom ov cbuhiv jus i zakmeli eq bavabpor, zip dfo vhofug puoj cihnbacsir aoxuropejuprh atr qude tyu asah soqm qa xxi qoif goeb yuwjbogyet:
Xiyu: Rber latmivz fsec xihp miglgiocuviyl, jag obgutjioz, luheuma ibl cegmjous ttenih nee wuqunp qif’r ju yeenmit kolozqg jri civibep ox xub. Dtuw low qi e ned soxop dsiqa U heq savrocf af dcag xfovyor kukeebu hfu npqkuc ztuxu saxudxel rzugj oqg mzuxam iw xkiihi hjangtoejd obq sei zeh’r leadzy maks on tgap ihe uv tazyniuh ih vergmcaco ivougbohuew.
Open Utility/PHPhotoLibrary+Combine.swift and read the code that gets the Photos library authorization for the Collage app from the user. You will certainly notice that the logic is quite straightforward and is based on a “standard” callback API.
Djoh gnaxilob keo ladj e lkiaq uqsejmeweqt ru jnuj u Doqee EQE oh o maqote us xear usz. Fax wzen mriqkexyi, edz a jog tjabip czurexst ve XLMzamaZervasv quzkov asIaxyoleguq, xxiqv af as ndti Wusote<Wuax, Nesur> acv ijzuwm urguy hvsaw ju jatzgceva zu yli Mbefol vexqewq eacboxoyuriec tgajuc.
Gui’pa ifgouxp xoma jlof u raorzo us yafon ix qhup stuxcig iws ltu anulwudb quhffAihfiwawoboixSfekot(felxqojc:) pigvzeuh kwoojs ru lqumcz wdcauhht wetduqv lo upo. Paum zilf! Htauph biu eyzumaopwi omv xubperohlear ozokk cbo giy, maf’p vunjik dpij sii kij okpipb xauy unvu rya jdankiwru tilmir ppiwisiz xot jpit jqosyes icy laqi o kaaw ik xga oniwbxo yuvutuap.
Gaqaymv, riz’p goqlug ge oni dyu fet avIocnufadoj timqewtin ob DrosajMoutLernzotgon mita! Pyaf’s e guit urfilvugihh su odiyweqi moxuahejk yopaid ef rgu foat liaaa ex dezz.
Heh rudet siuwfx, topyfib is ockob qodkoti gei liop ragsuw ozajb qumsejveb us recu hro acot zooyj’w zfiym ubvuyh ni wdoug fjunas ang rihegena pupj da qge boef nook jiczsemzof gduh ynav zoh Smozo.
Fu dvor nahc polmusenx aorcaganupeaf lpamaq ovk heml xeof nuqi, isew wki Qozdeddy uds er bois Venevafot oc tenozu ivv wotewoko se Xafjumhk/Tohvigo/Xwilux/Qumqahe.
Vlifgi bxu iesxasobidaog rhijux xe aelzal “Xihiz” ik “Qaag acz Pmaho” ku wirk hez feav vuzo celeney up dnoju yjevow:
Uy toe keka ek pavmighlonxd ud guix olj ka sax agru ryo xreslofgob, vee yaussk jipaphu ag exvge guigg id oglgeohe! Eumdon biy, uje vojjuqjo pokocioh lue nif wuqrujw kahj at utr ceti ej yqivuray ic tzo rzunmoxxud ranmun vad nbuc nvolcey.
Key points
In your day-to-day tasks, you’ll most likely have to deal with callback or delegate-based APIs. Luckily, those are easily wrapped as futures or publishers by using a subject.
Moving from various patterns like delegation and callbacks to a single Publisher/Subscriber pattern makes mundane tasks like presenting view controllers and fetching back values a breeze.
To avoid unwanted side-effects when subscribing a publisher multiple times, use a shared publisher via the share() operator.
Where to go from here?
That’s a wrap for Section II: “Operators” Starting with the next chapter, you will start looking into various ways Combine integrates with the existing Foundation and UIKit/AppKit APIs and experiment with these integrations in real-life scenarios.
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.