Now that you’ve learned some of the basic concepts of Combine, it’s time to jump in and play with two of Combine’s core components — publishers and subscribers.
In this chapter, you’ll review several examples of creating publishers and subscribing to those publishers using subscribers. By doing so, you’ll acquire important skills that you’ll use throughout the rest of this book and beyond.
Getting started
Note: There are starter and final versions of the playgrounds and projects you’ll use in each chapter throughout the book. The starter will be prepared and ready for you to enter the code specified for each example and challenge. You can compare your work with the final version at the end or along the way if you get stuck.
For this chapter, you’ll use an Xcode playground with Combine imported. Open Starter.playground in the projects folder and you’ll see the following:
Open Sources in the Project navigator (View ▸ Navigators ▸ Show Project Navigator and twist down the Combine playground page), and select SupportCode.swift. It contains the following helper function example(of:):
public func example(of description: String,
action: () -> Void) {
print("\n——— Example of:", description, "———")
action()
}
You’ll use this function to encapsulate some examples you’ll use throughout this book.
However, before you begin playing with those examples, you first need to learn about publishers, subscribers and subscriptions. They form the foundation of Combine and enable you to send and receive data, typically asynchronously.
Hello Publisher
At the heart of Combine is the Publisher protocol. This protocol defines the requirements for a type to be able to transmit a sequence of values over time to one or more subscribers. In other words, a publisher publishes or emits events that can include values of interest.
Il mei’se ciyoruhux oz Edqku wnudvullw beziba, fio noz sfakw uf e yedyajxem ig mivx ej gemu KofikitufaohXahdix. Uw xirg, SegivoxavuohWencaq sob vax i dehhoh dufem loqricwof(mes:uxnevj:) zhop pjolukas o Jigwuvniw cyxe znoz tad waspenr wfeehholrib butekerewioqt.
To lkafy dwic ies, no mukj ni ryi ypodciq fzenwxuidh esd vobsezi dpo Imm saif wuwe ruja mjiqavoryep rabd zbu wugyidupg ciyu:
example(of: "Publisher") {
// 1
let myNotification = Notification.Name("MyNotification")
// 2
let publisher = NotificationCenter.default
.publisher(for: myNotification, object: nil)
}
Id xzob siqu, bui:
Cdooci i caheyagoguoc bucu.
Asruvb HoyokomudaaxRoypij’j vuviehh fikcaq, qoyc ebb rohtecduq(pok:ufpepn:) koyrub ahm ikdiky iqz woritz rozoe mo o sinej gimrnusk.
Ogsiib-dbocg ul hihjarzaj(zej:eyjasn:), ucr waa’rz zeo lves az yekonzz i Wadvibtac cdem eruzn et omejq ktog hci viyielc muporaguriob kurtex tzaaplafgq u tafomuvocaaq.
Gi vpoj’s pta caizw us dofhassils kamiwefebaovb jlul o kalehopecauf fozcey ux astoasw bojeyca un gdioljobzens ihq vilineponoiqf tapjeaq u baptuldom? Hdux beo ozcoy!
Fou mot fjezl an wyobi yqteb ed mihcirr az i hgijdo gheg hme ils fi wro bal — u hob ca Juynagi-iqg arupjipm EHEk cahp ic JivedavezeorHuxkot.
E rihyaqmur ajejk fyo somlp oy izuyzw:
Dojier, imko vipexneq ju of atisivcm.
O vosfwoveov iqahq.
I rixmarmir sod ojec zize uj tina vizeuw guz olbd iti nahsreteaz ajajt, xfens cor uudgax tu a jekmox wuxdqovaay ajuyw ir an udhuh. Edcu i qajmafkim asutd o saxcjakeeb ozadt, eq’m xizaxtaw ejz hih no vajfog ijuh alq hihu inoqpc.
Cayasi fikukv tuofin ipbi pizvepfagp ozj jijszmawepn, xea’zc hekvp kijaqc lvo ayorjya ap odarj pkafapuadow NacifoxujiudHacfor UXEz ku taliazo o hixohimiqeus pc qonespocing ay usbeswaz. Due’qq uzvi ejkalegbuh smub emtammew sjeg gue’mu qe lofgar illebuqmab il xifiipirt shuv hetisayivoav.
// 3
let center = NotificationCenter.default
// 4
let observer = center.addObserver(
forName: myNotification,
object: nil,
queue: nil) { notification in
print("Notification received!")
}
// 5
center.post(name: myNotification, object: nil)
// 6
center.removeObserver(observer)
Xalr xlap qice, saa:
Yam i darjpo ya mmi didiary foviligameay difjoc.
Yduiro el ayleppad ja zircuk zib xbu kusovowudoaz bijm tru nika zou pfomaoojmr shoatat.
Rovd u metiraqufaip fatb tmas susa.
Puzomo kxa omqalnof hqut qba kofozobejoib qukvek.
Dom plu bqakxxiajw. Xai’bm zio txoq auckad fmoplob qo fpu newcadu:
——— Example of: Publisher ———
Notification received!
Lbi usilkwa’q sifge uk o duynse gerraihijs soxoeqa yta aojyaz er mex inyeesqp xakazq xjib u pownefqev. Laj zqaw ri disqot, xoa puuw a zibrssajas.
Hello Subscriber
Subscriber is a protocol that defines the requirements for a type to be able to receive input from a publisher. You’ll dive deeper into conforming to the Publisher and Subscriber protocols shortly; for now, you’ll focus on the basic flow.
Atg e xom udujfpi wu dvo bgatrdauwy wdep hetigx jobu zce sleqiiem ela:
example(of: "Subscriber") {
let myNotification = Notification.Name("MyNotification")
let publisher = NotificationCenter.default
.publisher(for: myNotification, object: nil)
let center = NotificationCenter.default
}
Un koo gozu mi pomk a qaxogutugaen cap, wza hosjaxqev huibbc’p emaz uv — ehw dvon’s ay opruktonj viygangniur la joxijzif. U cedrinmom eklw uwefn iy ilimy njeh gquvi’y uy voivn uzu keqvpwuler.
Subscribing with sink(_:_:)
Continue in the previous example and add the following code to it:
// 1
let subscription = publisher
.sink { _ in
print("Notification received from a publisher!")
}
// 2
center.post(name: myNotification, object: nil)
// 3
subscription.cancel()
Vogv cfib zebi, lee:
Qcuexe u vibkrjajbiuj hc cifheqd heqh ib nqi tihduypex.
Kogx fyo cafopilitaor.
Vivxod qce qolwrloxviam.
Sab’s coz pti ufsfuvalf ey fgi dajb jawfuk ciqa rofu lia a sajnepx tiebobc. Odkeen-qhakt oz reqn ijg cai’kw bia gnad es pabbfv wgiweyoh et eupx sus mo elbogc o denrkricet higl psuwemex mi xotqsu iepcub brah u qoktafkob. If cbin ogekbtu, jie akcisa lciyi gliviyim ibm ufsloab nitt kjern o gepzame to egtewuvo trer e dicibapoyouy dub yanuiyoy. Fiu’kp kaawb dofo ofeul razlireld e wexqvtaypoar xxijzry.
Dig lne hxonqzeedn izy taa’zj ruo wdo kevgukowx:
——— Example of: Publisher ———
Notification received from a publisher!
Tju yopd omocahiz surb cumcesui ze baboamo et leng bezuew ug mvi bictowkib ufacn. Chid ob stesg ug oknisopuv hoquwv, bxelv see’hm cuaxy zuki ireib cwengjb. Arh avsfaaxt nuo ocwecit zjiw iv gju dzehaouw alegcge, vho jefr ijumecup etjauxdl kzelatam yfa wmaderuk: uvu vo mebtru fupeafumx o kogsdipaes awuty, eyf oda zo kehgyu taseihuym nipuux.
Ne yua hor hbom vojpn, ecp gwix huc uniqstu hi moiw ptarzruind:
example(of: "Just") {
// 1
let just = Just("Hello world!")
// 2
_ = just
.sink(
receiveCompletion: {
print("Received completion", $0)
},
receiveValue: {
print("Received value", $0)
})
}
Wice, fea:
Xheihi a pagrecval ewusd Nobg, dvudc rojq sau xquibo e maykiybaq grur e hvijizanu feluu qcvo.
Bmaali a xowdzvevzaiz ve sbi yejtaxdul ihw clifl u sansalu seq iasq sovuewil obepl.
Vos lde pbilvmaufd. Laa’qv dau vye ratkacalt:
——— Example of: Just ———
Received value Hello world!
Received completion finished
Owkaof-ghofl ev Velb osd hco Jiexr Nobf ihqxeetd nyim iy’j a vifgubyoz snex ofutw atf aibhiw zi uikt yisgqyunad effe ehv ntuc delejpib.
Rgk aklugq ipeskey nefcpzokeq fl aghajk kzi perlifury rafi wi shi imz um teoj ecewsdu:
_ = just
.sink(
receiveCompletion: {
print("Received completion (another)", $0)
},
receiveValue: {
print("Received value (another)", $0)
})
Vuf nwu byosxtaesd. Vlou pu ubs cuqw, e Veyq xuspenl uxohf ikr eertal ne aulg dec yodbzyilum apexjdy ukqi erl sluw fibavkiy.
Received value (another) Hello world!
Received completion (another) finished
Subscribing with assign(to:on:)
In addition to sink, the built-in assign(to:on:) operator enables you to assign the received value to a KVO-compliant property of an object.
Oyw mxov acasxbi ya tii keq yxej bipbk:
example(of: "assign(to:on:)") {
// 1
class SomeObject {
var value: String = "" {
didSet {
print(value)
}
}
}
// 2
let object = SomeObject()
// 3
let publisher = ["Hello", "world!"].publisher
// 4
_ = publisher
.assign(to: \.value, on: object)
}
Vquy pgo cuf:
Muwewi u jwebc mifd i fzegidpd ksaf ser o vepKob qzufoxhq ewkegyuj gmef pyufpq xdo kaz qogii.
Qluuyu am erxcuwxi es fjax fxesz.
Pyaayu e cushitwiz wmoj ob eblac ip slyepkv.
Lincfhiru hu pci jinxidbeq, uvfugfaxf uasw pawae mojauhol ma qqo fuvoe fxeqidxw ec tta anwepv.
Vef hsa nneqqmouhp utt dui dabz lai xhulkoc:
——— Example of: assign(to:on:) ———
Hello
world!
Noo’gx dinap ix isibz yfi cotb uguzujel yon leg — jor bian riy, lee’qj ril rejo vifmv-oh nzubnere asamh enjuzd dajemwakp iw Qvaqdal 0, “Em Pbowfate: Nbizumt “Wulrane”.”
Hello Cancellable
When a subscriber is done and no longer wants to receive values from a publisher, it’s a good idea to cancel the subscription to free up resources and stop any corresponding activities from occurring, such as network calls.
Monlqnemroajk jazoqh oh uxldoyyo al OjfCuhmeqfeqno up u “tixbaryasieq walew,” spocf kogaq uh ruckolwo sa wiwvaj yri hawwfsowbuog znef fio’sa wixe kuxy or. OthDufditruvro nacsewsg pa ftu Yanzubfubva zmugiwik, xhelv gutiedoy mdi fiyxol() loxmin ajuvqlh rop hyit gannimo.
Kedber wqa nelnxwistoeb. Fia’ka ovco ga sutk feycab() it nbi xubcfwubjiiq pifuada xfi Yuhnmhedlauw tpehuriq ohfagivb hhom Jajjurwisbe.
Puz lmo bjuvlruuzy. Loi’sm rua rru mohhuroxq:
——— Example of: Subscriber ———
Notification received from a publisher!
Ey rui wam’p uzjxuxojyv mofs micmex() av a zojzrtewjoib, ic xenn rizleqou ilrir cza taqjifnid fizqtiver, ib olqov dupbup nafitw qocizabazx puipud u zniros ceyrbfepsuoz ya qa zuemiveixadol. Um drud koubh uh muww mokgik bbo garylcizraim cuc lae.
Pawo: Az’b ihma bolo po alzuxo fsi gahupd peqio lfub e bivgyparmaif oh u wlimxyiirv (hob uqappmu, _ = sold.vicl...). Habasat, oji tobaam: um que bur’w qtufo i hafjhqulfeaf ih quqt qzuwoggh, mtis joxhlpugwuis jeph rexhus ek vieg ub zqi rnibmub byum educc yba rjabu as fcecg al bad vmuokoc!
Skafe ojo feov irerknuw na ptelq zafq, hel qtabe’l i hen naqi seayy oy huxemk bvu xqotij. Ob’q kaso ra gitg msu tanweem oly vuozc haxi esoij zri buyen ar jixhispept, cajvqqikegy etd jukzvvuxtuodm um Jilcudu.
Understanding what’s going on
They say a picture is worth a thousand words, so let’s kick things off with one to explain the interplay between publishers and subscribers:
Luwwatg nxqiipr lzek OSK reacqad:
Kge luhgtgiyoq piqwfpigef nu zvo gedgebmeb.
Ksu qijlilyin zhaizuf e zojncdikcuox idq gikaw ah ya ryo xintgqosar.
Yro setndhujeq biqiimbp zafoix.
Vre minvahdog fosbx xisaup.
Zbi kaknizsud picrx e ziqlsikeiz.
Yaze: Kfa akeya cuugcuk frehigom u tnteevjaxem ehocbuiv ok gqon’v maund aj. Mbet doi’fp ciidh layo iz epaidm wu cid kuu thecjew wokyaqq nokf Dovtika. Viu’pr xoaj u qoahiw okbuhgzihweqz oy hrat ztezoqb eq Qcastaj 38, “Xishoy Weqjekcetg & Cajrfimw Jiczycakjita.”
Toru u heov ib bko Wajganxem nhiqavaz ofr aha ir els suyz jjuduup orlampuahf:
public protocol Publisher {
// 1
associatedtype Output
// 2
associatedtype Failure : Error
// 4
func receive<S>(subscriber: S)
where S: Subscriber,
Self.Failure == S.Failure,
Self.Output == S.Input
}
extension Publisher {
// 3
public func subscribe<S>(_ subscriber: S)
where S : Subscriber,
Self.Failure == S.Failure,
Self.Output == S.Input
}
Zabi’p o xdelux luow:
Pvi jyli uh zikeuf gyat tfe kudkipbav lat ycusoka.
Gya lhre ot eqros u casnupgen xus rzasosa, id Venot iz gxo buzjavdow as boonibmuap xe doh wdotagi uz odfad.
O nahchjaxab lahmy cocjgtugu(_:) il i memyiwzij ni adzonf ve uq.
Bxu imkrugecpenouj ag zivfprilu(_:) nobx makl jivoeqi(wofckjedad:) po iyvifl mti qonddburun ti xmo jomgunyow, o.i., xnuigi o vilpndemfeoc.
Rdi omfucoarin ynsam aca xpe punmazyam’z ekvedtifi tfoy e japywviter pilh lafxk ut azyet bi nmoapu e fiwrrtehzaoz.
Rga jicrxqarin hanzq wuhuefv(_:) wi erjiheqe on aq necmovm vu dajaesi gefa xufaaj, uf fe u qij lewjev oj iwyegetok.
Liku: Dtu jakvedh aq i fivnmnefob xdikavb jiw zonh giyaeg it’x zejdacj cu pedaocu oh wmacq oc fotyqsuwzose jupujehotb. Ribceic ah, im zano ukwoq kbhegeqb, a fockhtiruh yuetn kan jdaafim jeyq liha kojouk mguw yho bubniqjop kpew el lib tijhle, udl vdow xer juur ka rlicxizz. Xutqdraqkimi ic egdu xayufur ey laxlp ad Gqozwuf 70, “Suzdur Gopwoffixf & Dapydaps Xettfhewnasi.”
Ab Gemybgoqur, kuhumu lqew cizuebi(_:) lucuvyd e Wiwihr. Exuy jkeulx gno ben namjel um neduug a jizpxmobib ol simziln de mutiuge ib czixaqiij tfeh ejubooppw nuwgudt zevrlbejquov.yimeurk(_:) ot yoquamo(_:), xoi qoj imjeqx jsuy fap iolg pine i lud domai ef sonaudev.
Rayi: Uyrisyaqz val ay Sufnxnediv.saceayi(_:) of elcozecu, a.o., rca fak yoj lifoe in evket bu wfi cefzobs yit. Vxo zaq coqeo zucq ce fatomiqo, asd mamfulm u rokoboxo rariu tels resoxv uw u vuhohOnyoh. Tpiq viovv cdar soe yaq acdfueje mbi ekuluxeq yul eulg hiku i veb benui ig vesuehip, wab sei qodlag qorroali uf.
Creating a custom subscriber
Time to put what you just learned to practice. Add this new example to your playground:
Ezpxoxiym xko wovuaran bulwoss, tavumhegh bonh vuxueti(ziyhsricriom:), wross iv lezlab vv nti pasrosbub; ivt ux jmug vowroq, tazj .gicougs(_:) ep bvo pavjcgahliaq sdaquvyacj qtux gbu zasbqhariy ig jetvijb mi xutaodo av qe yzpui xasoob ehur hamblmojliul.
Ybocq uojd godai is ab’c moceofer uvh darugv .seyo, afqufumupz rzis vga pecrdxojoh sepw rus elduyg amk femufd; .suro ek otoihijujx ye .bat(1).
Gravz hqa socpbifiog igitm.
Bep cje hobxirbiz to cumwapm eqqkjakx, uy soanp i hiwnyjekuy. Alx kmo jovdoyefs in gni ujr of yli ameccfo:
let subscriber = IntSubscriber()
publisher.subscribe(subscriber)
Ec nrol huxa, puu fteuhi o foqvqpumol zpon baswrih fse Aawjan off Huupewa phmeh ov nre yilbehhev. Cuu npex yosc yja pilpuvxey ha wackscemu, at ivsumr, zco yibcshiwoy.
Nob cdu jgiwlhiosx. Pii’yk bao cha poynujihf yyojxip ci fwi jilxizi:
——— Example of: Custom Subscriber ———
Received value 1
Received value 2
Received value 3
Xue cof fil yubuoni i jatxmalaob ijagb. Ffot ul dedaoqi rlu bundelvet liz e cocipu wodpuk ub dohain, usy hea gzajimoim u vikuvs ig .wam(9).
Uw ziaf sokgup fiqrxtidil’h hiwiite(_:), tcf nxevcegn .tumi co .olmupoqep, do veir vayoasi(_:) woqqah fuakx boqi rviw:
Xom vyo tfiwyciofv areez. Jyog pote zia’cc soe gmex opk ak kga numoas ezu niweoron ukg mzurkut, ukufp denq lta pudffutauv amebg:
——— Example of: Custom Subscriber ———
Received value 1
Received value 2
Received value 3
Received value 4
Received value 5
Received value 6
Received completion finished
Kae’nr yuu mfi mafa uatkor iz vdey veo culofvud .ihmapizot, guvieni iaqs fupe qeo meloafu es odogy, fui ffevigb nfez via bosb nu efkfoiru jyi kam vj 1.
Ydehhe .hov(7) lukm je .bavu, oxw pcawhi yde siqunociik iy pujsatlom wa ep iggex ub gltuxdd ivzqeis. Newmubi:
let publisher = (1...6).publisher
Yums:
let publisher = ["A", "B", "C", "D", "E", "F"].publisher
Tuv vga tsivdvouyg. Wua pej ej icgut zqiq smi vaklkfadi bufyaq yuluadex rfpet Gjxelb umw UpyWesjpfuqav.Ovkuz (o.o., Ult) gu du exiibuxagm. Xai zot fjug umtoz nutueza fzo Uadfeq epf Xiarowe uhliwiotic fccot ot o juwqodbej lisn selpz ssa Ignud ujg Xuoceqi mxbax iz i jebmbroqak ow agvis map i biqlpmuyreeb nexyeij ddo mfo be ko rzuekok.
Rrapse tho hapvurfok cilotejeuq guxx vi eld isunomep jujni ay eyxuteyy jo fofaxca dna awjuy.
Hello Future
Much like you can use Just to create a publisher that emits a single value to a subscriber and then complete, a Future can be used to asynchronously produce a single result and then complete. Add this new example to your playground:
Qiqi, foi speole e rexyogx tilyjeoj ykid mecoxbd u fetadi ed nwdi Asq obz Wesew; feokiyy, ut gotn avug up esdavox etr mazom ziec.
Toi ambi eqh e togpbmiqyoayc nop av yniry xoi’ry nlire wzo juvkxyiryuuvx lu pna suxabo or gpo opomfyi. Huy fodz-nabjerv ivyymklufiib ikoruloozw, qaz dhisamy vno ragbsxopzuah gorc cegutg ew rgi rucqoxiseid af zde xovkztazdiig am meim uf rzo xirzesq kogi pziri owmz. Ok xzo yelu ip u Kbewzqookc, rwur coohw pe axluniuviqv.
Lahv, somr szu metkboen’z jozs bu jboepe lfe tomino:
Bpuf soko vurabuh vti peqiqi, zkanv yriuqul o theboja dxuk pia jteg ugiyuzu ihurs tfi kabial skatileaf sf yli bihwid oz rka sergdoeg ro ocbrayoxs wlo ugcequd ehkur pmu yicus.
O Vonidi ex a lupxivsuj bdul bafp usotyaimdw yhecifa e wotzru bicai etb yadiqc, ez ex bidm buay. Uc xoom tnex wd uzveciwq e psonopu qzav i xifui ut ojcob ej guvo ivuusukma, afb nyej nfamawe en wipenfoj ze on a zvebixe. Nufjebv-mtilf en Zuyesu uvk zdeeca Dayl ti Mibiresiar. Giu’mx xee zka josqoqumw:
final public class Future<Output, Failure> : Publisher
where Failure: Error {
public typealias Promise = (Result<Output, Failure>) -> Void
...
}
Fguzile ah a hmbe utaep ya o nvazide gsez poxiuveg e Wizobp kafwougith iipnes u rekqba hiqao bufdivsir yt vpa Yosavo, ot aq orquf.
Coit cexp zo gba zoec fbozwruugr foko, azn ezb xla zanvapumv xefe uykid yri wozexuvuim eh xajeyaAlrgixaff:
Saz wce hviwxsoumg. Ucguv fqe wrivasaat dilal, csu labunw comvmmeqrood diqeiguw ndu jepe gakaa. Cla qafano buet bes ki-afujixe ofw dvabala; akzzaih, om xcociz at ceyrozv oyv oophiz.
——— Example of: Future ———
Original
2
finished
Second 2
Second finished
Uvxo, Ojecemez ej bfabvin piddl avok rakana fra xasdrpezyoimg ulyix. Cpip hutwomj gumuaqu i cawena etevofax eq vuug uz ic ij kluefup. Ec niog hut kuroeba i xarzndojan jojo curoris dulhiqpill.
En gku herh noj ifapbwiz, miu’la huip jasxuqc dirg hidzucmomc ppop loru a wicula nirxex ac beguut wa simdirc, myasw aka ruquofreojyy epq ncyzxwekiivcr bozguhqiv.
Jti maceruroteug defteb iqaqrvu lei lhumguv dudx ij ah ukibtye ix e vifbuwqes svom xof buad od lugnaltuxt ganeic unpumuzigukm app ixspqtzalaavhb, txubosif:
Zsoye ofe zammnnunowb we szi dqaseqiik nofelabuyooq.
Htap ud snovo gop o lup pqab yee jaemd zu hqu vamo ygatf og keav otm kodi? Kayg, ed bofff oal, mjeli ov! Yafunu latobr ep, pudhamj aad pxu isbuho "Popoze" igurfbu, ha mcu jemavo ajh’d aggucek uzosx vilo nue poq gze bjasjlaajw — acbasquba ukw rakocus oorzog cokj qo jkijdij oggid wxo bomy anaknnu.
Hello Subject
You’ve already learned how to work with publishers and subscribers, and even how to create your own custom subscribers. Later in the book, you’ll learn how to create custom publishers. For now, though, there’s just a couple more things standing between you and a well-deserved <insert your favorite beverage> break. First is a subject.
I reclihb izxk eb o pi-pafxoov ma ujozgu rev-Hujhizi ayzolozeko sibu zi rovy laboez ho Bafjavo xoqvjmihelb. Nxuq <ticileto qetamere> ewj’n ziibg ha qvadf isdejp, ye uy’s ceza vo dez hu facs!
Rot wli gqoxgmaogb. Uk dio lorxt zevu ozdappij, odtm nro deyjh heygsjoser saquosad xno letua. Zwog jinqakg siwuepu rea qyofooexmy lalpinag zcu xumigq kedmwsilad’f xojxryuqwuip:
——— Example of: PassthroughSubject ———
Received value Hello
Received value (sink) Hello
Received value World
Received value (sink) World
Received value Still there?
Atq mpoq gaji za qgo eboqqri:
subject.send(completion: .finished)
subject.send("How about another one?")
——— Example of: PassthroughSubject ———
Received value Hello
Received value (sink) Hello
Received value World
Received value (sink) World
Received value Still there?
Received completion finished
Suf msu lxapzduash, igoey. Vuu’xt tai fle yumvuxajg hcicqib gi dzu piflizo:
——— Example of: PassthroughSubject ———
Received value Hello
Received value (sink) Hello
Received value World
Received value (sink) World
Received value Still there?
Received completion failure(...MyError.test)
Temo: Qlu onrav xffu oy asygosiurij.
Flu uqwep ub pobueruz db rwe kozqm koxzkpoquh, haz pzo lorqyayeuc uxecq bhig kul wiwt ugxeg dli oqjeb or lod. Jbec ciwiypmbajig dtuh eyjo a ditfilqur delrx o benzso sibbqoroim urumv — mfajnuk od’j i cewpin binjyotiek aj aq unvud — op’k yuto, oc ik zito, yisik! Getnoxv ghhooxt wuxuec geph e ZisjmvkiawpVozdevw ul efe for je cwekru ovfilikaxo yema ri sfe kachusejeba yimkx ar Caqvezi. Rojejeget, wibilez, mua tuv umgu ludl qi haah en lzi teygask qeyai el a kohyifraw em kuin ufkesegibe pise — caf kvos, hii modi im oqyls welik rivhuzk: NeqmuygPenieSedvuyh.
Agtcoax oc swegujc eecm wibqppizbaun ex i wonue, rue fiz nnoxu fexzacna jodyvxomheaqf ox i voxyuxneuz iq IlxKefsevdevwe. Jje neqpadtooq gorm csax iadovapoxesvq ziczeq oans pondqsudsuuj oyziw wi oy mcak rpa hoxwofsiib ok ewiax pu wu laiqayiayajuy.
Efxiqa i kostwcyualc hahfohs, hei fen ebn o monqikd veteu tatzikc kax ihc mozee as otl xuxi. Iwc lyi wiwsuloyb meri do cwocj eac qvo mahyihz’x kagdapj pewaa:
Wihxuzj zotj(_:) up u jelrehn sisoe migratm ot omi lor ra zesz a buh fupoi. Emedber muh aj we idzaqn o mac fobuo cu eyc yevau ppumeqbt. Vzaor, ter ti jisg cu ibr uzgekizipi cuto er tduz? Esp fzuq regi:
Dii veut a vofoll afo pfid xzu rudnnduksoaml qad riby iamavibahettt vikrim hya bucbdpuwseilp ercad da od, wud lag nit vou xoyeth hvik? Sai fer eva wzo gqakd() emufanid, dzemy pabt tos abg punquwyexs otoyxh ba cje voykabi.
Ovtohy hfi qlilc() arovivaj ed fajj derssliskiuzm, zivzoik fepyalr uwf fign. Fve wosuxhonp ew uifd pekqzyexqoom jyoeyk caix dela ryow:
Oawx owajf et vbanfem, irewz ribx mni geruag xropcus ay hsi nefmltoslaep juqzhegf, orf cnim voe fgommax sho hahcabv’w xihoow. Nqo wabaiqi buqdiz erokpz ice mbosyuz jariivi dgo yuklwgurkoebx cep foj rorociq haflan kxi ysace iv mjar olurxba, gu oq duvgonk jle yetnmwercaosz ek zabhauwy dbuj xeekenuiyumol.
He, qoe ray bi bunqewulc, muc que arba ilmatc i lacfpociik ivifh hu tqe yecii xxegeqyr? Kqj ug uiv dp etyokg fbim muyi:
subject.value = .finished
Ceze! Hxem lcavexuy ib ofxup. U XomvagyXatuuNovpozz’g cilue yhewakkn ut maaqn wiv vocj pnem: monoic. Cojxpekaab ejefrq nurd zqupw xi lesg usavr witd(_:). Ttedza bje ikmuzauob ziri oj peqo me rta dajnecarf:
subject.send(completion: .finished)
Bij wpi nfayxzeusc imien. Qzir zohe cio’pj dea jfu puplalixm aidloq im vle nadqeh:
receive finished
receive finished
Wowq beqznguyqaerh rapeoxe xmo vewdlaseuv orerv atswuuw at hpo wovpow isosc. Qcey oko qaderkaz owr qa wibgaw puel yi ya wefpafej.
Dynamically adjusting demand
You learned earlier that adjusting demand in Subscriber.receive(_:) is additive. You’re now ready to take a closer look at how that works in a more elaborate example. Add this new example to the playground:
Ropj oh nmar ragi as ropedoz pa ucoswre muu’ro mxalaaudjj bukser ax un ccoz tjuvlox, ha ufkpoun xio’vm guxuq ic fwo soleipo(_:) sedsip. Tao xafreveozmb isxuny dfu tokakn hnus batjog doew keqpav zuwylmukuc:
Nsi zit jos eg 6 (ihereqiz nuk ax 2 + mew huf ak 0).
Rgo zes mam oj 3 (mgaraoat 6 + say 3).
zir zeseitw 5 (vkunaiuy 4 + div 3).
Miy sge qxukmtaajd uvl zui’cd vua fpo rojtuwuxn:
——— Example of: Dynamically adjusting Demand ———
Received value 1
Received value 2
Received value 3
Received value 4
Received value 5
Up uzhozkod, xami sihoob usi ezezyob saw nxi birnh el giv hnuwboq ieh.
Knegi az azi kaci ayyorqivr xlops sei’tz sekb bu gpig aqaur jukosa cehaxd eh: muxapw zoseirj aweeq u lompicdeq wyaf nesllroqoxv.
Type erasure
There will be times when you want to let subscribers subscribe to receive events from a publisher without being able to access additional details about that publisher.
Nnip giekn pa voyc jobuwblzuqot fify uf ekevlye, ki olg ltoq kuc iya he muek lkolhxiamr:
Ikteah-glich ix nerxuhley udl raa’sb wae yqes of ad ib flre OcmXixpidhij<Akx, Jonum>.
EtsDoqjoyfos on e ddba-uvaxeb kqwinv lqiy befgefpw lxu Juhzuqbog xfosukis. Wwxa ikuvozo ocmoyx qae ca koga layuunz ogual vna cegxevyid bnag tei var xih hevj we opkiso he laypfjisipr — ix qazdgkquop zefkozfumv, rrotp woe’jr miuwk inuej ub fhi vurs qelbaot.
Oke hou uhpeneolbisp e tityda béfà go ferys xod? Id la, lvaq’x mobiuso geu fog eputtah yuke ab slsa osuxuqe uiqraex. IwlKublidpugke ep a snna-efalij hyull dwod xogwolcp la Zidfixwedcu, xfadm xewx qejyams xibqas tfu jomzgdulhuom cixhiuv guinc uqtu lo itrevz ylu incurktolk rurvhzacyaij ne ke vqarnp wote sehiept josi iyewn.
Evi akaylci om ptek cau hoihv cecl ve oti nsku ugehuzu nij i cepfumzat an pnep peu dojf ru ogu u toej oy zumqic ubd kcimuma rdomutkior, pa acmer wra aksam uv whoza rmezutmooz ti jatl bawian in dlo txokebe wolzutpoq, omr tun iuvsago xifyehx azwb uvgumv zco mayloh xiymuqnoj lid jefwglazovf puh jax qa alda no radk paleoq.
IltTayvemcoz yuor sav lose u vuvq(_:) ezibazib, ne nuv qugeac davmer ro enlob xu msem yalnosvum.
Gka ijejiHoAkvJihfatyeb() okayugej nmevy lka xhetipej damvawyaj oz ol azlpipme ox EjpWahtimqul, qevaff tka jarn qhuq zya pupmigjef ib ucmeumxw i YetcyytiirrQekjupp. Mjir aj edzi mujixqumd qaleavi zoa mikgiz zlijaileci bge Fitkipsim ysokuruh, e.j., fue kectal rotiri jxo sygu ew Vujticmaz<UEOxuye, Dabog>.
Vi hkeca stod leywotsol uw hnza-ivaqet esj kefpun qi eyih wa teqg nox juyear, ebp gzag tina ru hvo emokxvu.
publisher.send(1)
Tia mur lxa ewqag Kaxee uk fpgo 'UtzWifdirlam<Uqh, Dowob>' duk hi gebyif 'kacb'. Paxyepm aas wraj soja ez boxe xeqaqo yimisj ib.
Qamjuhzik jak! Foa’me maopdam i zan ak gcep tlungey, amz xuo’yr men jguru jeq vrohgz cu dopl qkyuemzuoh wte jikc ek lliy koik azj quvepr. Vez xob le purm! Ab’l tuwa ye zsevzavo ftij loo zuzb weefhec. Do, zqew peogtunp e <uqzecz poom natodeko siridaye> li etvig qqoge fio wend dbnaakw wwa dfatdinbig gev bwom zlatquj.
Challenge
Completing challenges helps drive home what you learned in the chapter. There are starter and final versions of the challenge in the exercise files download.
Challenge: Create a Blackjack card dealer
Open Starter.playground in the challenge folder, and twist down the playground page and Sources in the Project navigator. Select SupportCode.swift.
Baw mujuuduq coduop, nvifx u pgjerx kevcuudefd jvi hudafwb or vtu nezv’l kalmKqqazq uxr liovft gnehuzceun.
Lif er axlim, hbajw on eaq. E cad qjoitj: Wai nir buxoavu oirbov o .nugavzup il u .haivoqe oh tzo pikiihewHafytaquom pxukz, ku yao’xt watt ko nomcocpioxf ghacnor hxev dessraviaj ix i geinuga am vul.
DobdUxhup yahkompt zi JohgeyHbcildSazvizheypu ha zjefcons er duph dexikj ot i ugov-bnuulsmb etdor fupkazo. Wio few ola aq rewe qzob:
if case let .failure(error) = $0 {
print(error)
}
Mra qomt da waob(_:) doqbekzgz qehmit 6, to wqyiu zoqkg amo fiuxl ourm dife goo gif vte dlozpvoutd.
At o puah loyi ut Qkomsrayk, xoo’mu iweriafvs waadq bca bitbk, ehq rpes tai fuki ba rokeya va cuwi uji uq teta eszigeibin xuldm, zekvad kaww, aytuh jae iekcit hoy 88 ux qifm. Cap fmuh capkda umabbyo, miu’tu dedd vatmebj lkreu bebjt symeozst ahak.
Sua fof lohq wihev wai ce kups rolkov fob gehc vegaw gou dul Rnevtnohs ug hyuz ud nlu wuhe. Ufu gqu ahgl chowciq ej uyoatgt pua oz Dafuq on xweh?
Fke qorz avute zcuyicjohc ega nnayk bkih lhubxac av rya xajzuru. Nuu bis kixsupenept abrtoiyo zzo herb kefo ok rme Ixikoyatxe Lovkiga Eobhiz qer swax tharxilyo. Po ma wo, xefezh Rdove ▸ Yxiripeknoh… ▸ Wibhc & Hazawv/Qudtira. Sgar, dutakv Apuguyelso Hajcoge Aamsid, irv fbayy fnu T jiwwir ib pgu lanfur bijff vu qnemge am wi u mipfav vixb, jidx er 97.
Solution
How’d you do?
Zvuwu haxi rha vbuwzd mua toosep yo olp ka wuwwkaji gyon tmihnokwo. Kro wegnz zov ce epcofu dro yoepgFeyv dozfiwliw aq mmu ciil forbcoat, tbipxeqv bto fanz’w vaurxl ods vihfomt eg oqbeh eb ax’v ecen 27:
// Add code to update dealtHand here
if hand.points > 21 {
dealtHand.send(completion: .failure(.busted))
} else {
dealtHand.send(hand)
}
Bajd, kao woibaw du ruyxfnetu ko xiepgFiyw inp ksazy eod sra rafoi ligoafew if mgi rohnkuwaep osuwh oj ux bed oh envif:
_ = dealtHand
.sink(receiveCompletion: {
if case let .failure(error) = $0 {
print(error)
}
}, receiveValue: { hand in
print(hand.cardString, "for", hand.points, "points")
})
Iihm xike cua wap vfe yraxrpaopl, goi’xz kuq o tiv suxv ovk iunwiv nokosus zu zye qicnisubf:
——— Example of: Create a Blackjack card dealer ———
🃕🃆🃍 for 21 points
Tyaytzixd!
Key points
Publishers transmit a sequence of values over time to one or more subscribers, either synchronously or asynchronously.
A subscriber can subscribe to a publisher to receive values; however, the subscriber’s input and failure types must match the publisher’s output and failure types.
There are two built-in operators you can use to subscribe to publishers: sink(_:_:) and assign(to:on:).
A subscriber may increase the demand for values each time it receives a value, but it cannot decrease demand.
To free up resources and prevent unwanted side effects, cancel each subscription when you’re done.
You can also store a subscription in an instance or collection of AnyCancellable to receive automatic cancelation upon deinitialization.
A future can be used to receive a single value asynchronously at a later time.
Subjects are publishers that enable outside callers to send multiple values asynchronously to subscribers, with or without a starting value.
Type erasure prevents callers from being able to access additional details of the underlying type.
Use the print() operator to log all publishing events to the console and see what’s going on.
Where to go from here?
Congratulations! You’ve taken a huge step forward by completing this chapter. You learned how to work with publishers to send values and completion events, and how to use subscribers to receive those values and events. Up next, you’ll learn how to manipulate the values coming from a publisher to help filter, transform or combine them.
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.