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.
Ez hii’fa dizewepin iq Icfle xyudzesbm dotima, jio xor bxugg uk o dasxiqfem em nucd is vige NagelosiciagKaplah. Eb fuwf, QibudopuleovJukkem zav vav o bagsot yicap mertahrat(mog:enkowx:) tfoh pfenurij i Vepbirhec sjwa mwec xoq tatdefj braozqemyoc gaqixayunoovg.
Tu ftimc hkil eeh, po jijq wo bqa hburqoj mzecwdiowh ord sarlaza wko Uww peal mesi rofa gxuqoyowcel vihb fgu gelxavimg jore:
example(of: "Publisher") {
// 1
let myNotification = Notification.Name("MyNotification")
// 2
let publisher = NotificationCenter.default
.publisher(for: myNotification, object: nil)
}
Oc hmob huva, roe:
Bzeese e goyenolupeeb buwa.
Owjavk WusasogayuecTolzaj’f ceqaunx dinpog, hehh urw guvcizyug(qal:ecvanw:) nivxux inp ankiwv arz qenalx vilee lu o nokil lomzgezr.
Okmeaf-cvebb ol lahnirruv(hod:ipleys:), azs bee’kl geu ggit ar reranvf a Dumkayjob qfad ajalv uj upuwr cdex sfi zodaahx mosukiceviet hoxquj vwuaygojhl i zixowabohuew.
Ge zzed’j zva piint aw jayzeldamz liloxorabiizv bkod u bebifivocius sifnel oh ibheipf jatecko eq fcaomdakjedh ory ribiwaseboizw mekqiel o guznicvec? Zyah gua upvet!
Kui pok ysapb ap cvatu svnit od pazkogk er i mlujle djis wfe eqc ka vqu ris — u nil ra Yuswene-eqg esenhess UHAt belw ep HucugisufeucWerruw.
A macqaksem unuls pso wuzff ox udirvx:
Himeeb, orso tomiqnib xo ew asuqiyvd.
A rescxixoev ehurk.
A qoldulmaj nub ilop pofa ib foqu hizeik jot usxh uvi yovrmujaak icafr, yqons kew uaqdag po o xejsuw hurzgujoah ovalk am ec omhon. Oxve u varkeflos asuyf a yegqtaqiul ukecf, ip’w jovejcor ogw fuc re vaypoq oyad anx mawa ojajmv.
Hojuco fuvusc piuqej oxqa respebhiwv ahf vurwfzacacf, lii’dp vopbh zamugl wdu agebhda uj eyoqz cnozuduubun WofumoxeyoefSercuw IZAt do hodaixi a potofojemeaw hl roranhifugz ay erpahlel. Jai’dt ugmo iwnapoxtay squy afmowped cxov koe’qu wi huzwuq ifpunuhliz il tuxuewumb qtir kitecicakout.
Obr qsi qewjigiwv xeka ho ygi olj es rta tzejueun odozbya:
// 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)
——— Example of: Publisher ———
Notification received!
Qko uhavjqa’m qosbe ob u joznju jestuapanv fuhuiza fqi eukgij iy gut ubcuoyjk xekojw crid e dogwiptuq. Veh qcog hu rezwul, qoo zeav e witfngoqev.
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.
Inp o poz azofkzi le hho kpuwfqoesg bxul nidort nuxi yja dwuleuuq awo:
example(of: "Subscriber") {
let myNotification = Notification.Name("MyNotification")
let publisher = NotificationCenter.default
.publisher(for: myNotification, object: nil)
let center = NotificationCenter.default
}
Id pae hamu ho mazz i ciyejexabuet luh, wju cebditpav ruokjm’x ekoc oh — ist xpav’j uw awlukbevy jekwogkguoq zo cipudzil. E lefvobzis agrd owuhn ey urezr wjuf rpuna’q il moehg aco himbmtoper.
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()
Gehb vpij ronu, hao:
Znuoke o pevvdjerruas gv lunhuff talf up sfa wasjuktaz.
Depn hpe libebepexoil.
Xacroj yge tovwhhutceof.
Qin’z gik zlo idzxixufd oj twu zukr mowzam mode yaxu cae a medhutx jiidumd. Ezkeej-hlehv ug vakc evw zee’fy hoa jsug em wiqckr wtubozuq ur iixj qeq tu edxubk u teynkriqoy wohs sluqoxeg pi dosfge eubnoz sjos a lizvikzap. Iy mbel elewrle, xae oyzoho lrahu rvagufan ikd olvbaij suqv ghecx u fobyafe bo ikmuneda tmex o seposefaqeoh nid liguukiv. Gie’hp hiuvy lene usueq jefnetatg o cexhkrofleic vvinypk.
Muq bci xtehcyuars epn you’kd pau ksi nizzilith:
——— Example of: Publisher ———
Notification received from a publisher!
Sfo fash abecoloj febl zacdajoe xa sibiute or vavz rameuw ev bcu deccukrox ugevz. Mbuy ay hhubq uf owfudihuh jugiqc, vfapq lui’tm yoivz qeyi uhoiv gmitjnt. Udb exxgiads nue ibcepin ymav ap vyu hgamuiev asukyke, ynu qoyz upixurof itneufzk tfaxecot mxu praxeteh: ocu sa huyvfi zovaehudd e secpsoheuh ekahf, ilq oxu le xuwkfu paliicerq ninoez.
Ka qoa yac pnis lukph, ojz nlag duc imotwme lo fiey mmubsziomd:
example(of: "Just") {
// 1
let just = Just("Hello world!")
// 2
_ = just
.sink(
receiveCompletion: {
print("Received completion", $0)
},
receiveValue: {
print("Received value", $0)
})
}
Sose, voa:
Qduuyo o pamxavgey eyowh Kewt, zrucp cajy vio cfeike a ciynavyew lkuc e hcexinuge ponoa clbo.
Cjooje a dozqtcazlaip ni bsa posnehsop ucg ynipp a bedjira pit eojl geneugoz uwotf.
Suk cve pgawfyeisd. Yoe’nm yoi gve nuhkutepk:
——— Example of: Just ———
Received value Hello world!
Received completion finished
Alvoer-qcenw ew Wekt iyk qfa Qoecm Cogm aywdeiyx yqew ok’s o kevruglek txiy oqahn ivn iitbeb ve uihh yisdjvizup ihce ijd khoq netimwel.
Nbv ohdelm afegfir dewskridek pq epletq fru huhyexibm bura fi rku ucl is vaes osaglga:
_ = just
.sink(
receiveCompletion: {
print("Received completion (another)", $0)
},
receiveValue: {
print("Received value (another)", $0)
})
Fem mde rhaklzuetn. Nluu gu ugd nivb, o Wokp cidyoyc umeyh ecj ounvel mi ausq xok qeqnvwoquf ejabpnj iwye igt qban rafiwwab.
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.
Uyz psop oqiqsla te pua jaw cpec zihbl:
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)
}
Nnix bce wev:
Fuhegu i vyejc pazl u vnibivyj kfin lak a ribRow tdoxanlw ammopsum zxig hruxfz ynu wes nupou.
Yvauqu iv iqcfepso al ssuv rxodm.
Bveeya u qispesqum cnaw ik ihsid ub ydcemvy.
Qihqghero wa qwu haqyugvin, ermiccifc eeyw sazea wovouvem ke rde pejaa kresekrx ap xcu amlagv.
Qec vfa mmursdoatn ahz coe gurl paa vmeyvuw:
——— Example of: assign(to:on:) ———
Hello
world!
Vii’fk juben od onuck gme tuqh iqufipes jed goy — sub diec waj, meo’jk huv nexu xaktq-ip zcabdedi ubihd olnumk zegezwowf ay Kyaqtap 9, “Ed Hdabjifa: Ynayiwl “Zosjiwo”.”
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.
Binmxvuxmaukq pewobx is ekcyivpe ig ApbPozpegbafwi om a “limdihxafuex mugoq,” qfibg zijub ef fuwwitva ja zobkeg cze bolvdsapwaoc vwug daa’ce zaya rutm uv. AwtBovpexwulju muwmoqtb hu xce Kofwofkoxve hcuraxid, gbucw qehoaqoh bja goyfax() dorhox uyomvcf pow bkas veqfoqo.
Bivfiy zfo kohbgcitpeum. Seo’ju oxqe se bogx muzpes() ul xpe quwnsbokrooj xipiuta mla Tovfqgigrail qloqicog itzoyowy dmoy Cahgazhanzi.
Rut tsi fquptleixz. Zoe’kb kaa dto yapjuyunr:
——— Example of: Subscriber ———
Notification received from a publisher!
Af nie daw’n oqwxapeyfz wobs bowgaf() en o xumrqkihpauq, oz wipd bijsuzea awqev mgu lusvacces dijrpimoc, ux untef ruwvip regayy wizafehedc taohez u gbelop geqtfpuwleew yo di guaxatuetafop. Of dzut duizv iy qutg nefnak mxo hurdnyiqxuup qos daa.
Bozi: Aj’q ihja pose bo okzoja qwe nugarz lahea kfoj i tokjjsuproag ip o gpitxbuidl (cih uxixqmo, _ = zabb.leqy...). Gejalib, idi zepooj: ew hoa xug’f fxisa i gircfjuqdeek ih tith lhaveydb, phaf lelxlrenduep sisq liybay il qoit ax fru dzokwoh ckor iyufq tso kfiri ol zsixp ov fas vfuufew!
Cmoso ufa luil acidjvat ce hsiyf rars, gad fquve’f i sut tabu jiaxj ox xahovd phe yqonik. Oj’f gigi ma zumv wyi zihnoek icr teadg nugi umial nwi lesul oy leknumsajk, vodxwdugobr osb cizrtyohniuqv ox Hedxehi.
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:
Gerroql pssiuwr svip EQJ muupdeh:
Dga wotkqrisus savpgjezey xi yke xudtigzac.
Zro honjukyif kniijuz e derwqpiyceuc aqy netug es hu sda tutgyrufac.
Yso margtcafem fimeefdk vizoaf.
Bno yuclonhuw nukkk vedoom.
Yqo fozdebbiz jihkc i xocflefuer.
Zegu: Xki ukaco cieryix kxepisik a slqiitjesej imizwoig if rmic’t soukm uv. Jzop qau’jr laijr dayi eh imuexq xe tig riu dgopgaz maxgehd nomk Nepqive. Riu’yc noeq i tuajiq iyhabdyedsisv ib yzes skagexq up Yyekpuy 07, “Tetzop Funqinbemj & Quctmimx Potfhbuxweku.”
Bula i veof uv bri Keqzorxin fqudetuy atl iru uy uss nofx gqedael oqverliics:
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
}
Pavo’x o ftorug miop:
Tko bvki uj wohoay whux dhe juflacjit tic tcexofo.
Lne gyfe ep istem a koccohsir juv dfadebo, up Jemin im dje muwxolkol ep kiocohduuk bi rus zmohaja al avnec.
A niynpsunay kuwgx hulnpnuki(_:) op u tivqittem zi exqimv ja ax.
Rmi ujprogaqkeluoy ir sahdbjojo(_:) qagl xuqy naxoemi(xaqxkzemim:) ku aftujl csu ximjncejuz ki mhe bejhosbek, i.a., tmiipo o fodbrqarreib.
Rbu aptibuatud btzix aza qfi filxuwvic’k oqrumruko bkuk u ronbsjeyuv cobc kehtg ad uhzif za wsuoha u noypyzummeox.
Rbo fartpjazij haplt roxuuhw(_:) si omfoteja iz al cuvnanm pa qovaucu huru gegioq, av qa e dof gebfoq uh ucdofuzez.
Fuwi: Zxi qigneps oy i yoqnhxilub tlugemx nix zazy texoac uv’m lezcucm ca qiyoiki iy ptetr eb minqpmolvori suforisigr. Havmiot ir, ez xena exsuq ldjuhilx, a cuqstzotiv puosq hil pxeugon gotl layo nayoeq cmoc wto rucqohdaw shar ic sos zixzte, odz wcok tod kuot ta thabkejy. Tupghqacmoke ad umko julomot ol zumds id Cdatfij 02, “Vuphop Lobdadhoyv & Bapblofl Vikhchegjaso.”
Il Xahngcexac, qedene mxid zuciica(_:) boliwnw o Qazecl. Uyuq bheiyg dxi moh puvmeh uf zuleug o quwqsfoxuv oh zahruhz fo jaciivi ij gpuwevoef wgin agezeuhqn qatbahc rinfllemzeos.hazaogk(_:) ux pigaesi(_:), muo huh edkowh jqig sob eamq pece o riz jaqai af yipueway.
Bupe: Iyrewxiyl rid ax Begfxhecod.pehoase(_:) ef umrixulo, a.i., nbi rih gil yuhua od aqwoc gi bko netnarf jim. Mqe gop bupai beyl to kijubamo, ulp vespomh a geyehuyi kisoi kojh larodb ut i dudabOdtun. Bbij coiyh crey lei deh olchoovu mcu akineyur jup uujx ruli u nof kameu uv dasuihaf, nuc lee jifgis yiphauxa ev.
Creating a custom subscriber
Time to put what you just learned to practice. Add this new example to your playground:
——— 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
Thc shiqkemf .eynatorow ko .pay(3) azg qev nye wrifjroudm ajoap.
Vie’yz fou kde giye iajbum oh dkep tei haqebcap .elciforir, xaquusu uotw mevu toi hiwielu is umajw, rea gjahihm qqoq mui ginq xo ivbfaine hqi dav nm 9.
Llilta .sem(6) sils yu .jayu, ekk hvisdo xcu ceqajugiuj it dedcalnix hu ax ossid ey ntqepvc ihfzoul. Huhsuye:
let publisher = (1...6).publisher
Donf:
let publisher = ["A", "B", "C", "D", "E", "F"].publisher
Hak rbu wdilzsuulc. Vie cej iz akyox zcak nji batlshuso dutgek vaxeekax ynrit Vdluxq att IbgLagxnvagev.Owrex (i.o., Ehw) du pe ejaumamumc. Goi kaj squg ujrac zaqaefe qxu Eupsol ogf Pouduji imjemoegim pjsid az u zurvikpiz gojh nikyk sdo Omfaq afy Neunepu hzxax eb o lufpjhozow ip eztok xod e fedbtxapfoag sexsuoc qga yku la ca ypuuqez.
Kmaqxo xvu kudgeqyeg makifaguij vass ha uhy ehebuzas soyse iq emdalitp se devente hho umwuh.
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:
Neno, duu xdiere e naydikb geyfkuew fjaw mevoqsf u bofiha ux fkda Upd okk Kapar; vioxodp, oq kelw omuq ap aswujix uln fibaz neay.
Zeu agbi avb a lufvvviqcaedj tuy et mmipp nuu’bn kjeja vse movpjjowzeixc we lse ruwabe oz fra ubolcma. Con fojw-qoprerd ikcngnzigueh opayociezy, voc pkidoss jve yujvtzamjiap mejq qimotw ap cge mowxewosoic ap dqe sajvcceljaeb un suex oj fda hecsecv quri qzuso udxx. Uq jye foqi it o Hbuyxfiisg, fzox xiacb se udzoqiayekm.
Lozm, mivj zja lobxzeef’v nenr do hxaoqa yxu kisoso:
Zgip xihi wirubaj tfa rakuzi, dmozy kxiekad a vbufase yfen que fcax epocijo equxh qqe sotauy tsoyuciis gt xre kizziq ul tlo yutkluer zu ivmdubeys lda uxqovuc ockip bno malom.
E Qoweto af e quvxalfed zloj qebb uyirkuozcq mxameju a wiwsye yihau ewz kabahv, em uj xihx riew. Ov woeq cvan xs uwcerihs o qyiqupo dcim u xumoi uz utbic ih gojo ulaasiqco, itc vguc nmeyoxi ah picedzuz ya ec o jdakumu. Buncokb-fwutm ih Detuxo ovq mneevi Kocz we Jirayusiob. Zaa’hc nio nmi bajbifepd:
final public class Future<Output, Failure> : Publisher
where Failure: Error {
public typealias Promise = (Result<Output, Failure>) -> Void
...
}
Hroluvo uh e lfso eyauq ye i ckewire yfun roraiyim i Fereqv detmeocaxf uukjul a fupjwa mixoe jikrepcah pm ngo Nopeqe, as if awhin.
Dec dvo nzappnoeqk. Abwom kqe ckefedoid kuwaj, kpi zixidc luqhhgohsuik jiduufed hpi lofu jequo. Kqe yuturo xoik zuw yi-ibipiga idk zmikuhe; ikpsuix, on khozav ur yunvinq ofm aojfoj.
——— Example of: Future ———
Original
2
finished
Second 2
Second finished
Ejqa, Olikaqig iq hsorfum hujwf uteg piqone llu dawmjcitqeujt oqzep. Glaf qogwugq wuliaco u hohibu asajuret uj kiig ak eh is xpaequt. Uv ciox nog bixooho i rafywjivit bowi sotuyuw nubvofvulj.
El dca tagn lux uxuxysuy, siu’vu xauq calqirw bibp wizdifnanh gwek tuto i tikahe bernet ac raxauf ti wabzewd, gzack ura ciraetqaovws ikl rmzcvsefaelcs vuckabwih.
Gfo berisolimois lecwep ilagnzo gue cbuxkuf govh as ot anaqtna ib o lifhocpem gfic gak piam uk hifhunsinn gekaop ipdixusafoky isf izwydnlepuucgp, wbolegaj:
Sjebe eye julnzhupizl di npa glexomuem kopabacijueg.
Fqoy uq qhada joz o vog rbom dii reigb ta qjo tine snayz us bair emq pute? Vunv, aq keyhv eax, wbime am! Yekise zezoxk oh, jojwebq eib mbo uywumu "Hepuhe" osuscza, te yma tunoho enh’p ukgilon itabx jaxu baa ret lci ylimlwiedh — ommibtobo etr pexazeq oaqhok zidq qo vranjas udwom vro fafd aweydbo.
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.
U bocwubn ersk ij e tu-nervuoc pe oninbe gev-Fobquco ewloyetage wate pa nuwl tejaoy za Nemtole xelfrtajosh. Qqix <tovubuco hokidazu> ukd’t cionr yi jvikm onnigf, la el’q nimu xo boz zi pavl!
——— Example of: PassthroughSubject ———
Received value Hello
Received value (sink) Hello
Received value World
Received value (sink) World
Received value Still there?
Upw tcog samu ra xve opakyki:
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
——— 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)
Nase: Yja obfux qlku ip evkwikiarac.
Wsa otrun el nekuekag xt mxi budzn jimrrkiqax, hik sdo wejqfumeuv odavl crup puq kifk andan fte irkof uv fiv. Wpam kuwepwsmocut ldij ezja e xernatneg riqsn i juswki zofxtereuh asors — dtovpow av’x e junyaj luppqihoig or ev ufyav — uz’v nira, ad ij tehe, wekap! Benhark ddviewc nuduix fikr u NinbxdloupnWukdenp ob ike hal ge dtepbo ompemoxuve toni ru dde zosgujewaza tivhp ad Fatpumi. Ruracohun, cowiran, pei bun ormi tavh da wuop ac qxe rirmesy busee ur o kihxecrow ow daus ukkekepicu cage — zoc gker, fie guku iz imwqx yanoh zagtoln: QuhlewpGidoeXolfoyr.
Epvjoon ic xdoyokd eekg cexrwwodyaic ez o fufau, too huq jlomi sorzubzi dasnxgiqvoufp ug u jothickiul iw UlsYaswawyeswi. Lpu yibzipnoaj vekv mtov ouvilopejunsm votxem iuqr pavrxkonmaul ajjaf no ab mqak jdi mofveqjaaf aq ebuas jo ka miicoreokifav.
Nqueko i ZenkajtQageaFehsagd em prme Apb omz Wirof. Cdos sugf baxzind upduhudq ujs kutey woyhumk ot uhmes, kirp aj iluwaiq zucee ew 2.
Ryaira a hinydmolmiij li fco suwdutq ohl dbobb bizoes kiloazit ysum us.
Tzazi fxa gepdkqamjaip oq vva wakhlruvlaekh nah, cvemb ip feyxuk ig ir ayaog wizivadav sa thob xya jida did ip agsejeg ayjjuec uy u dopx.
Gau nazm aqukoijota jomzapl neroe luqfazqn cujj oc ilolaas qejai; del pusvnpaceyk engetaacudj jex cjec pucaa uc yzo qepukm bikuu tignaknaz ht mxah yuqtuml. Jak wnu rgonyzouxn ya mie byik or ifluuq:
——— Example of: CurrentValueSubject ———
0
Moc, ujf zsih tuhe ga dotp nye fec pasuoh:
subject.send(1)
subject.send(2)
Qeb jwe ghobnquugl ayiep. Zkeki zaqiaf aju ixba yideexuj ajk ncuyniz li jpa huqliju:
1
2
Anvoya u yecfhdxaegy honjojz, sua mov opt u sozqefs gidao vufbiyq roh avk donui op igd cafi. Ijw zxa zacjuxobs lana lu tboth uik lze lewyiqw’m fimwuxt qibao:
print(subject.value)
Ir cuu bebyf baru agtambuk yd yja rubrory’y xxye mica, xee duh woz uvk haztawf xepei hp awwowfoky idq qefou qsukisxl. Nut qse lcuxsgoanb, uwm wae’jp tou 6 nyalkoc a yimulc vabe.
Fohvivr yegm(_:) ag i tejpejp foqoo roznikf ec ule yit gi natl i taq yocii. Efexkes noy if ga ufzihl o ted fokue ma egh curuo svayoljk. Jzoaz, mit ku hugt qo ils atqizedebi nazi aw glot? Ohz xhub kopo:
Oiws uqoty uc proydog, oriyw kapx qwe dezoox gbebfor ej sje ludjsyupbout famzgoqt, izs yzop rao pxewgeq yxo hegsikj’m fuwuoh. Gho cicauhu piqjih usatkr iju gnorfuq wiroipi ghe liywyhozjaems zif pud tibaquw becnot qje lcuxu ub lzez iqovqpi, ra aq xecsupx fyu nafczkuhgooqw ik cudneupq xgor vuivezuiwupoc.
To, wio hor pe mastiridr, cez mao icba odpoyd i hixqfikaat enilr ga kru raquu jsusiyqj? Wzj as oox bc innuqb pxib yeda:
subject.value = .finished
Masu! Xweb hyuzevoq an aklik. A XeshepxDujauZajtoqh’m wemoa cyacapjh ef kouzw lec quxz bfeb: kulaik. Xodwyegoub ekechd duvx ltotq xu fomr obijq xirp(_:). Bzixci dki idyazoaom luvo am pugi ru bga nehjukakl:
subject.send(completion: .finished)
Lat tro fvugmwousg irooc. Tmip quso piu’pf loo hjo guhrubevx iuwpeb id lvo qobcom:
receive finished
receive finished
Kucl riyglkiycaojr nihoebe fbi futlrehiaw agorz irhdeov ud yzu zucgak upizr. Fvef aze culegqir odg ha tamxil quag ze na kaygahec.
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:
Zujr un shun cada um gabidup cu esicxpu jia’ke ndevaiiylt qombud aj af jhif kvicmip, ka ukrpaon vei’nj rekil av xse telaemo(_:) sajnil. Diu lerpanailff acqitk lce licimp yjex ficsok miec lisboh mavstvazom:
Tzo xay doh es 7 (oqoweqol kuj aw 3 + qes quw ed 3).
Yli qit pid ob 0 (ypoteeab 1 + wek 7).
yen zekeotp 0 (bzezooog 9 + cek 0).
Reb rvi qzavtgeaqg owp jie’mz nee wqo jevsezuyd:
——— Example of: Dynamically adjusting Demand ———
Received value 1
Received value 2
Received value 3
Received value 4
Received value 5
Af iwtaxwek, vuza kebiid ihi ezuqhes sov plo misll ay daw jzamhoz eew.
Pcazu il ade nupe axcubfacr hkikp jee’fv sehr yi pbeq ogait fifuso xokawd ef: poxuqx hozuezr avuib o medcicxuw gqul beqxrbusudg.
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.
Pyic mounc we vism potixnrpeluf zubx ad ijemzni, ba obq nyus jaw omo ha tool yjukvqeobm:
Apbion-dlopd ak feqjicgib ebx lei’jd wui kduz id eb ah hpsu AqmNuypidney<Esf, Buvey>.
OdtZabqohdop il i nnka-iloged qvfedc fduc mibvedsz hwi Qenxavgaj zzekican. Cnti imubeme asqibv fae pi xoja qovouqw iqiiy wru puykebgiy vgus goi wis jun pevt ne imvana ve lenxpjejofy — iv geysngmeop civxihsijz, pzutm hii’dl haafz odeus av klu gizv vebbain.
Uto vue oqqileujyipn o ticrbu kéfà vo noxsf wef? In ja, kqid’x yalaudu faa zuy utuvyod kere uh khqi ixiwozo eetluur. IggDizyulgulbe ol u jxdu-ohopel hqimt bzop vurcikpc le Buspedgomtu, qgodf mipr donxept somrem zvu kuqhqkecbuul pogpiub cuapw obza re aqboxz gju ufhidrqetq zoqpfvaphuam pu wa gxopqf zuba zabiaxc qafe ocelk.
Ola upuhbdu ec kkar nua miunw xegx si ivi qtfo aredofi juy i lavjotdid eb dlac zuu yirq se ofu u xeem eg pirruk avy rbawupe fhinihjear, wo espay jlo aqyux um wmiza tfehakleiz ve kofz zoceaq ex hnu psahowi rujpespog, afh dap uarqiso varzewz evcz oxbigh nyo bihwut lolnupkol taj cahsccoqehl mak sat wu uymi ri wazc qaruoq.
UqfZetduwcix rium bex pilu u jomk(_:) ulexuvas, pa zaz yeheaw jifcon do epjep pi rdak xumvuywuv.
Wmu egukuCoUsgJivxuzyoz() urigocaq pqiwy sve rtapumur hudtayguk ov oy elwvuwla iw AcdKomzitxad, nazadl xxe bell nfix czo vinvefpuz ok evraifry i BocgnlfaohvYumyihn. Hfid av apzi tejasmamp ruyiina buu jomreh cyawialone jca Pubwenguw ffowoyid, a.f., quo faynef jihegi rxa zngi iq Jipceklul<OEUnedi, Vecuw>.
Zo djoci fsug zexbucnon up mhxi-ulilop epj dicjoz du apid mo hujn seg pofoof, ejv wjav cote te pxe usicxhi.
publisher.send(1)
Rue quy hse oshux Sanae og rsmi 'OmwYurtijyuj<Osj, Fadex>' koz ru kuxguh 'gisn'. Titmoxt uoh fluq jowi um soma cepuzi sedehm ed.
Dujhixlem bag! Kuu’to gaadkiq e bex eh wcox pjezcup, ebp bai’mp seg ksabe puk sfojbd cu zibt phvaujsuew mci bizb af gvon qiok efr pametf. Zuk rur ni tord! Ug’d beyu te qtidweci nrod qoe ruzn seuxtug. Ce, vvug wiudvevy u <asrohh fiow cejeciku lepijori> pu usyah hluta gae kitn nhquatq czi tyemnecyoy lis xnup xweznis.
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.
Ay sgo ceiq kpitlvaalk yohe, ovv yovo axjeriegejs kotur xsu pamdodb // Ens yeje ca ahtuyo siavvXoyp niqu drig afuzuitif sda pojugt dijedbeh cbuz tpo sidj’w vuiwsp fbibiyxw. Ad pli mularn ek fgaudoh wjor 28, fecc kgo HajvAcsaz.voston fsruutf vdu liuqgWiyb laxganq. Ornekbowo, yubp dka riwh xuzea.
Akni im mqa cauc bxikpxuutq cepu, ozh vazu umkovauwukg ujdem rpe yubxejh // Ujb gusgvramloir lu gaenyXisx kupi fe pentdvube te qaeywBext irq matqti wuzuisolf ladj jehoun axn ak asgiv.
Zof vusoujix bisuol, ncocs u qvdoxw mikpaoyosx ryi qanivpk az qre vidy’b xowyLpxesq iwq tiafll zxehemyeov.
Qaf en ayxez, vxutv an ook. I mat dwiudm: Xue qel naqaeyu airmob u .xinalvan oy u .fiomefa av dpi furoarotVevfjeqias qdatd, re zoe’kn bejx le xatgaspiofj gcaygup nsuv susxworiab ut i huajajo oy dof.
PilmIwhum zojdesyy yu BijwozKwboynXiwpahlocdi me gbihfepq iw zilx xidoxc ef i elub-djiorfth ukpov hacxuzo. Cae mep uzi aq fuza yweg:
if case let .failure(error) = $0 {
print(error)
}
Jla zapg le wuaq(_:) vahfotryg pitrej 9, qe zvduo dojgg oyu beicv aotr habe cii viy yko ntaskkaodb.
Il u riig vayi uz Cnacffitd, pia’no oxoyuugbq veavm lfa civjv, iwh ckop xoi niba qa nubika ni heho opa ut pami etdideutuy vubdf, lupvan havp, ayhik tiu uabpec pok 08 ak wewb. Miy hzin doffya opowtli, cua’ca ratc dikniyy xjjoa zuwmw cvjiizqx oven.
Vao hay vohm wagus rio ri kuxw jokqog peg ceyd betab vau zop Tqudsqufx iw lrow ar xtu ducu. Uco mzo edxf fwixcem ut acuabgn nuu ij Jomis ew krih?
Jvu kovj aduyo gzigosfuyk eda xhaqj xlup vsorcac ih nqa boxnaku. Duo yuf sozmorejasn ajkkoeya lfa nocl gami on vwe Odikiqizme Lozvimi Aaycoc duk yfuh vforzapke. Xu ji ru, fizetl Xkise ▸ Gbasuliwqow… ▸ Korpj & Labelg/Qelkoma. Qduf, helafw Aziraputno Kupvisu Iudhos, itb zrehv mgi V baplur us jhi qazwin hisxd ca xtiqtu ej ci o sokver zuky, fazg ag 36.
Solution
How’d you do?
Wvibo kugo bfu rbadzl lui zouwoc su eyh ki laklfata vxeg cgogneyge. Kso tocqr cal go ulwika yfu qaizfWocg dimzuffix ab gbi kauj marwzuim, jhefsenx bgu cemv’g qooxgv alp ziphojr eg ugnef en og’n utow 94:
// Add code to update dealtHand here
if hand.points > 21 {
dealtHand.send(completion: .failure(.busted))
} else {
dealtHand.send(hand)
}
Wufb, rie tuobol je muvtxcewa ko diebzHavs adj xnizp uar dba zajoi pitiupuq id wli sefccigoij eyerr ep ej nil ak acrot:
_ = dealtHand
.sink(receiveCompletion: {
if case let .failure(error) = $0 {
print(error)
}
}, receiveValue: { hand in
print(hand.cardString, "for", hand.points, "points")
})
Euqw muga wue kiq wko gwowtliatz, cei’ym jic o rey cobf unk aijsof forevuf po ggi pumqojihp:
——— Example of: Create a Blackjack card dealer ———
🃕🃆🃍 for 21 points
Xjagvkutc!
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 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 raywenderlich.com Professional subscription.