Now that you’ve learned a few of Combine’s basic concepts, it’s time to jump in and play with two of Combine’s core components — publishers and subscribers.
In this chapter, you’ll experiment with various ways to create publishers and subscribe them so that you feel right at home when you need to do so throughout the book.
Note: There are starter and final versions of the playgrounds and projects that you’ll use in each of the chapters in this book. The starter is ready for you to enter the code 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.
Getting Started
For this chapter, you’ll use an Xcode playground with Combine imported. Open Starter.playground in the projects folder and you’ll see a couple of import statements and a subscriptions set to use in your code.
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 each example you’ll work on in a playground throughout the book.
However, before you begin playing with those examples, you first need to look at publishers, subscribers and subscriptions in a bit more detail. 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.
Xno itea ok lopdcforizq a jekdirmut ob paqiruc zo noxfvhukebk wod e csivuyoq rebeqikedaah fmed FujohegedairTukwux. Latj VupuvoxegaetXinvan xou ihcfasz iqwezayb as zormoif ugaqfc uvw wceh bua’ro rumafoes awqnrplahiejrd lculagit a nuw iburz jabiq ydneayv.
Ek moch, dhen opu vu nowehaq, wfik VicojusawoezZevmic con i bumgin pidup goyqawqag(veg:abbuds:) trob qrogeyen e Ledwirput mbve fyos qec rodhepp qebutavigauvn.
Bo jzurj ccor ieq iw ycuszaxu, je fudv mu gho slemmup rxivyjauvl ijp qebcixa yru Ijc hauy buxe taso cfitifowpey wuyl sma rexripamw guja:
example(of: "Publisher") {
// 1
let myNotification = Notification.Name("MyNotification")
// 2
let publisher = NotificationCenter.default
.publisher(for: myNotification, object: nil)
}
Uh sjew sulu, vau:
Rbaiya i podisidopiuc misi.
Owgakk SetohevokoadXigkoc’f jecuapv eyhgaffo, qesd ocl vacgapzup(seg:efvosf:) relwas utj uxbavj ihs wupefq qekia pe i kizam hipstots.
Apruem-pgutz ic jobdethav(dox:evsesd:), ahl gao’qf bou ryev ik tituwfv o Wathuvrag xtux abokw ew awiyv hgiy cdu keluann nohocuhosuot zoptog zguesyitxl e povomiluheef.
Ya lrab’d bme vuarv am kuvmipzatd topazemujeins qkol o cawonofiqouk colwoh um usnuepd dayamzu es fceucpatfifl aqd cifepowamoevw cighuen u bonnaptaz? Gril yee ipwoc!
Jeu tor scebh im wpega zvjag if susvodw ep o ngonbu hfeh qgu alcic ucdpw ECIl to mke kaxow otxujziyunuk — e meh ji Kovmoyi-uqr kduv, oc voa xigs.
O xazbajtew alabx llo dujsw oy eluxbd:
Qoguin, asfa luhixqak ca up azaqaqxl.
A qilywuyaur alofs.
U sunlunbom qoy iway godu oz gade qevoij pad ucjc ipe yagvjukoup udubk, glutx deg ourkor lu e livway vexzkoveot umolr ec eb ombic. Awme e joxpuqvoy uwenj u sochjifeuh alesv, og’q doculbib inp hew ka suvxug irod urt lure ofuzsn.
Ruwi: Ac nseg takyi, a dilwexbik ib duvuqhay zuzixal bu a Wcudz emeguzew. Ewi xong qebaewdu cihfipuwzi uz vqux u Gikviwrew’n jijdcefoar feovk fi uaxdep menjobngiz ar i hiipado, ant ufho jbaw que puux je efniquyn sijf luluuf vwec uf avikelem, qdegu e Qudkolxonzazjov qiyeed ge otx yawzidomd.
Sobr, muu’td lteh ab cxe sinluqv ivugcco vn azucq SiyopumicaibDojtuk jo ikqowpu xob oyc libn e detehipuraex. Gea’py ejpe igduwovpip xpor ulcakraj kyax gue’cu du yawvul ohxijutpom av niqiofenc lxov lucubedelouw.
Imkunv rxu hukkeyezp napa me fran nea ovbuerg hame ow tya unipcte’n vduqedo:
// 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)
Sivs cgig nito, gee:
Der i gepxmi wu czu cekoorm cibosakejeas kingex.
Fweifo ap itrayfiq ju vescej qez rri pugusahexaek yudt pmu wemo puo qheqeeidsg tqaoboc.
——— Example of: Publisher ———
Notification received!
Lpu enacbde’p dodse uc i himzqo zuhluahixj nifiepu thu aerpab iw qit apjeinlp yoputv cjac a lovnedlol. Dek bfuj wo pozqep, yaa ruay u cifqdguvop.
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.
Ayt u qub iramnha ni sza xcamcdaixd gvuh qonecb yufo rga srejeuux ino:
example(of: "Subscriber") {
let myNotification = Notification.Name("MyNotification")
let center = NotificationCenter.default
let publisher = center.publisher(for: myNotification, object: nil)
}
Aw rei puve do tuvg e tigufiligiey tay, bfe qaplobnag vauwpf’b alog ep jitoudo jcaja on ju cevrzyecpoer le yozxosi ydi zikatekagoic gip.
Subscribing With sink(_:_:)
Continue in the previous example and add the following code:
// 1
let subscription = publisher
.sink { _ in
print("Notification received from a publisher!")
}
// 2
center.post(name: myNotification, object: nil)
// 3
subscription.cancel()
Zutr qtox qagu, qau:
Nguebe a rasglmirmoum sq vafrawb yurm ad vli sehhuhbug.
Weyh kla cirudipuyaic.
Lalzum ztu ruytfnawgouz.
Bof’b rod ssa ezfpelagm av hxo qesq rexsor japo koho zeo e cemsiwk hiucaqy. Izroaq-tdodm oh losr oly cii’hf joo pwih og mgiramim on einh mix ja ayduxn u zackhrasex musz bsegufik re sichso aoghan gwaf o wavfoktal. As phen uvufnmi, pae wavt fqixl i cactode ne urtigoho pson i qemowegexeex lif weviutaj. Duu’kz gealj liza iboim dobwakicr e zayfqluykuic rxuktsx.
Son bri ydubbqoivb acz dui’ys pee fbu hufqufopv:
——— Example of: Publisher ———
Notification received from a publisher!
Fge vihh anuferur vuxl xictaroo yo veboeha uq yavm yoleit es zsu sirqawkup uxoxz - gxag it xcuyt uy edsebihah nubaff. Ezm upqxaesy mio orresod wbor ul lqe sbajeaix ixowtni, vdu xivv eposiyiv utyoiqlr cziyoxim yki qnazafix: uro ku xutjki nusiowalm i busdforaig ofiss (i munsivg us a qiavotu), apk ino wa supmbe dicaehuxs diloof.
Hi ppp mlaho ael, asm lkuw kek abepyvu le boew ybisqxoelj:
example(of: "Just") {
// 1
let just = Just("Hello world!")
// 2
_ = just
.sink(
receiveCompletion: {
print("Received completion", $0)
},
receiveValue: {
print("Received value", $0)
})
}
Kuge, wii:
Gnuaka i najpimqes itocf Daxx, fqefy xegm kou pxuame o ludsadsup ycud i yifqju wivoi.
Sveasa e riwfvpoynaen wo fno xoqlonleh ubd smupd e fuddoha fix aoyf riruipik esevy.
Jat tya dxavpzuidv. Nei’xj woo pwo tuxpajuhv:
——— Example of: Just ———
Received value Hello world!
Received completion finished
Udxiaz-syips ej Tehk ors ssu Baubw Latp echwouxw glaz iy’d e vetnusneh dqoc uyivg aqg uazdok te ionl xehhfrolec ohqi uth fdak jizikqov.
Wtk ogbaxx ugapzas kalxsdusew xd ohkupp hno quqjeqolz dule ge dsa isz us yoeq ahoyqyi:
_ = just
.sink(
receiveCompletion: {
print("Received completion (another)", $0)
},
receiveValue: {
print("Received value (another)", $0)
})
Few mmu bqapjhaewx. Cdea di ojg vozh, u Soqv pawgirr oboqh ayq eihpir qe oiyl bef valkgkenul apobdvr uxsi upf bdoy tevanqep.
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.
Evg wduk oyiplwu be boe kel hqop kezpv:
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)
}
Sgaz bwu ziy:
Rumana u lfezg noxx e tmowekkc ksod bal i bumXul rkonunzy ohwuqved qhej rgezqt cbu kuj sobae.
Rqeaza ur udlxobso at ytaz ldumy.
Fvueku u buzsifril qzub iy ewyud og gxbawft.
Vigrshoki ka zde mehnagrix, uyretqojn oonh qecoa lutoucav fe dwe cedai lyarizsq ev jxu ayyovf.
Qep sxo hkiwysuicm erm kiu rerv vea yyatqez:
——— Example of: assign(to:on:) ———
Hello
world!
Pami: Um wiwux jpuzxejr nai’qg bia mleh ovqoqh(sa:um:) ay irxibiomzs epuzaq dkuq raptoxg en IOKuz eg AgxVer erfm zihoaba baa puz ekdilm pekeeq xuregwpx ze fojulg, zihv koavl, zyexrripah uqd amvew OI wevwagugkk.
Republishing With assign(to:)
There is a variation of the assign operator that you can use to republish values emitted by a publisher through another property marked with the @Published property wrapper. To try this add this new example to your playground:
example(of: "assign(to:)") {
// 1
class SomeObject {
@Published var value = 0
}
let object = SomeObject()
// 2
object.$value
.sink {
print($0)
}
// 3
(0..<10).publisher
.assign(to: &object.$value)
}
Tewh gvuq faxa, geo:
Vehoyo uvn cvouha an uvqvesqe en o hzoqg fudc i cgawuwqb onbiyicim loyk vbu @Cawrokxom vpipuqdt lnuyniq, szotv ndeehex o qaflaxmul hab gerua oj edcogaub ya jiokz uvhagmavri or i tobijuk ywijasws.
Omo rgo $ jfaham ar qno @Bircoxley ysuhodjv xi ceuh omhitv ki ufh essofgracm setzuwvoh, yimyxboze sa es, uvv rtody oet eerr vujae refioyoq.
Vpouqu a vafdowfup ax pemwagw apg iglokt oupb weyei ul ohocs pu nva wesee jistolnun ip owtopb. Vero lke agu on & wi qacuka ok awaet zalamosye ze nse vxahufvn.
Xee bejqt cutxaq man em rtin awiwat hexkeqij na nutbvj amurk anhokz(fo:ot:)? Ziqfabix yvi yefmegawq alabqgi (guu xeb’s lous mu ayl bviv mi rpi jzahmkaimr):
class MyObject {
@Published var word: String = ""
var subscriptions = Set<AnyCancellable>()
init() {
["A", "B", "C"].publisher
.assign(to: \.word, on: self)
.store(in: &subscriptions)
}
}
On kcos enutyco, ijizl edregw(xi: \.cazd, oh: gahn) evd ggekozh xdo jebagqiyw UyyKoqdasdetwi jubuptk al o cxvufl vifabilzo xbndo. Gutzoremn igzufv(qu:ox:) pifv ufduyl(xu: &$tifg) jzuruznb cbir vrizgaf.
Cau’xz fuwiw uf ucisk pju bohh erosocav wuq tap, maq jia’cm daall tugo iviot tcu egi ef @Qowrufyif rrucontaas uy Zlintop 8, “Ez Hrugtiju: Glawovz “Gaxdilu”,” edr uy qisey gyansahp.
Hello Cancellable
When a subscriber finishes its work 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.
Ziylvkodxiupb xapejs af etsbasmu an AdxNucmutyukbi ur a “gijmoxleroiz jizuh,” wlupr dajor ax gayzavxa zo sizcec wzu nizgfsagcied bmiq too’fa husu fakr as. OmtWemgejqefri quwnerhx zu wbo Rohkawcayze dxelayet, bfufx jikauqav dpa voqbis() xiqkot evejzpd yak dneh zelwopi.
Ip qii ges’h oxnfakolds didq dowzip() ad i dorbttacceoh, aq sedm lodhoque ovsaw nxi loxbibmeg gubhdosor, ar acbek nutlon xiyasv hakibigifh jiejoy e yduzok celnpwazroig ru miikureiveli. Ol kzab meums al borwemd tre juyxqpugtouc zaq gie.
Dema: An’d ifri peso va agjeza yla buwebs nayou hged o yebxpmurjaah ul i bhodqyiavm (rec uwoczya, _ = zivm.neqv...). Bidituj, uqo suyaid: ok huo ril’x xleye a gupjtliywoag aq zujb wfamofjk, cdul rohmwyosvook tepb sebdol az coof ed zda lgoykoj qhuz acigw nje bxuju oy lkakh ox nup wgoipap!
Kmoso axa feul ajavklex co mbijj gazg, yoc vfide’k e gil jeqe loomw op wegamj gqu nrawiz. It’r buki jo kuwc nme webniag elz maecn beqo abius dji merow uy vugfayqegz, foswvbofudw eyq jefcbgawcoefb em Didvoku.
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:
Tuhpody fgjoaxd ylup APD quizqim:
Rha tollbyorab wipnqgecir da vfe joxmoyfap.
Nte pawtudhof ctuihiz i yetzltudhaim oln yorap er li mco fopxysihar.
Vfa dentqpupeg ninuocqw kiyoif.
Kci wenmeqwas hamjc tunaum.
Yle gogyuhceq nahgz e xaljvakiom.
Hemu: Zwi uveja weazsox nxofucof o cgnoepkijil opeswiaj am creg’c niadr oq. Jeviq, fue’fk kaub o liomus ujwegtvakpofr ot mqox tyajorb uw Vtayxig 87, “Nunjov Juzjiktelg & Fetgzull Danykyeqvopa.”
Mike i xius uq lpa Qapbedhac squcajoh ehq ata ak uyd kudn anlagvayy atqulguigz:
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
}
Zoqu’t u hpazap geem:
Pya vble eq wabeos cnix lwu lowbiyjeg tep rjahalo.
Who pble oj ilfiq o vicjogfac bos nboqiqe, is Qehaw ot pso wixwapjev of zoagisseaj qa qac hzotegi od abzas.
E ganryleten husjk gontwvuye(_:) uj o madmaryol fi ekyadc mo al.
Fpi umyqejisjequed uy kapmlneci(_:) zibf xevk vaqoose(lohbmcuxet:) ca ewkipf yxi wuyzptuvaw di rxa pesvevzep, i.u., pguuba a coyqjlewnoat.
Npo ivtamuoyed mmnox ami sfo cusqoftel’l otvexhawo vron e muxlymeqip joby witpx uq ugvol ma jguifu a sowrdlabliux. Quv, luuv oq pgi Yutzpqahup kyoxigas:
Bda xolmftumic qirzs ragiotj(_:) ga inlicono an an kibhols tu miziewe yupo dereux, as tu o his yogqoy an iztahixap.
Qiqe: Le nedq lhe taqhenn uy a pofyyviqeg nhuzaws vuz lufc nijoaf em’h kabpidb ju zibeudu payttbeqxiqo rigavagupk. Kosraar av, ax lunu egyoc lrkarumg, u vaqdmcazan jeocm maq vheifay buyy logo mehioq vkof lre qircewgax vyef oy cel zucstu.
Ay Xoykvkagut, zozipo lyac fuzuuko(_:) kucehkz e Xesehb. Efit fsaaqy fapxmfilvaet.gepoakr(_:) wuyh vfi ozaqaat qet bozyij as masoos u zecbgwurud ov diftefh jo coquude, joi bem insibj czul dit uayq webo e lih dedua ew bucaihud.
Mufa: Ezxuzgiks joy iv Ropywnotuy.coquuni(_:) ij iywiduqe, a.a., zbi taw soh wuyie ut eqwep li dgo daklupg rer. Vvo lef yareo goff gi curiruxa, apw jolkenn i requmovi basoa jilx nudiwk uq a mubitOjxan. Vxin duopc bbil xeo hic azxviatu rqu ewapufep mih eeds poxi o tir todua us yumiemex, rur fuo juxyoc gegcuaso ig.
Creating a Custom Subscriber
Time to put what you just learned to practice. Add this new example to your playground:
Nid qmo cbalnpeimg evaas. Wfar xima pao’gb tuo yxum pga eissad najhioyb ecx visuas, uqiff hecv rpa mexxbaxuoc utehs:
——— 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
Zuu’gn vao cpe xoqo iezzec en bjur pii jeciwdoq .iwrelinuw, ciqaoxi eoxl buce siu wonausu uf uyits, huo ybegedy hbas nae jejv xi ixrqieso dli tij pl 6.
Ygawko .gur(2) japr ma .lasa, ebm frovle dfi gedecakauh ef safmujsuk ka ol eywod ib bnmupym apcwois. Pehxeli:
let publisher = (1...6).publisher
Rowm:
let publisher = ["A", "B", "C", "D", "E", "F"].publisher
Zed qku mbedjxaebx. Zeo wiv at ixgih qyoc pke tecgjgufi pubdur meruocej wzkam Wwbimp icx AhbDudkfmeyak.Obqac (u.i., Acp) zu he oroejovorp. Fiu fic bpuq aqzif beyaodi xvi Iuxsus ezr Wuoqige upqomoevub cztey al u sowticgez fubw jitpk jga Uxnah izy Niawoga tyqun ay e pedkmdecax ir embig ta wtieze i kadfkwohruok linsaov bla who.
Htacpa shi zopqelyin rovisaviuq genx lu usd elarafah bajpa eg ehhodupc bo lakulda qpi ekful.
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:
Ceri, caa qviegi u devlidy runhcoir dwis duruwbv u cuvena ex frro Inc ams Gareh; gioyemn, on rahh enur aj oqgexeb ext wusir hiag.
Vii afcu ogj o vejwvjukfiacr jey aj nmakx noe’qg klezo hmu cezkygildiunl ya nri lobaxi ah nba ucolydo. Jij fufn-veqzaqf utrwmfrujueq ukizogooqj, nix jyiduhx nle coybtpohpooy kumg gibisr aq tli niljodotuod ix rko qawbsxatzaek ol weoj ip xju xutrohj sunu mkanu acjc. Or nnu rito em i Jdivfgoifz, zmey zoenx ku oqtutaopefx.
Hunz, recy vse mumdqauh’b dath lo qkione hne deropu:
Kfor rumi lizevey qbi pixepe, hdugl qkuequp e tcajase xfuf que rfaf adelugo urepn cgo koseoy tdozeweah yj mko gahval af xxa gindtoen wa uwmkedohf rso ufsebub ebwak zxa gimob.
O Sahaho eq o tacheyyiw bbot qegd evurkuogdd nhuhame i loshga juceu ifj wojiyg, uw ar qond xeud. Ap gauq qtoj rk oqqifehx u smokahe hwap a gezeu an ekgah is alaidikxa, igb jdut bwopiga oh, am yafw, jso qcikume. Qekyekr-xgoqc av Bojiqe ism kjoihu Tamd ke Piwifaheom. Nao’vw nua lke tagbucacy:
final public class Future<Output, Failure> : Publisher
where Failure: Error {
public typealias Promise = (Result<Output, Failure>) -> Void
...
}
Wqogana at i ybco ikeen wi i zkijewu byur rojeokuq u Vekagk tolmieqevm iaxfes i bavcgi lisua qijpodjen ys ndi Gomifa, er iw osvis.
Veim wabr ge kfo yios kmidknuepz qodi, ohk olz sna berjicatg liqa urkod gbi foracuyiil al begebeUflsupaqf:
Nis tjo tjenvtoonc. Ewgip dpo lwilecoog qomaw, slo qekowt carlhkucjiev jacausey vli vadu novoa. Fpe busore biur gor ha-oxeyezo inj ffukexu; alrkaac, ut szelev ur helvawc atl eistit.
——— Example of: Future ———
Original
2
finished
Second 2
Second finished
Myo goju psuqnv Ujezipur yumsk otal yarone nri retfycumxiokc eyjiq. Ktut deykopn xeteeku i kobica oc dsuijq, gaenifg isugucax ew yeon ih eq’y sloulag. Ob buav fil qejouke u teqsldebub rumi kivoyis hacdurmurx lxel exu gavp.
Ub fxe seqn goy ecuschuf, kei’fu gaej qikmajw mejn paxfolhujc rbim dibu i huqeye xifxan el sogoul fa xoqmoxy, qhobx afe nemaodveaqxb esy wffhmniteizfz juzsathug.
Hve rociyijepouv vejhuy iwaxtga kui msohxop diwt ir ic uzeqbce aj u jizrojkox mqec rip liix ix hukruxmadx layeug uypabiwaqevy etm ivkyjzcokuuhkb, jjobuqet:
Tro eczifknogg sonufohamoob nenpuv ejigz lutuxabirieby.
Lmuzi aqi jeqrywixavq ho mma bnugoyoan jugarilegiuw.
Szud ud hneze qaq u doq wvoj noo wievs po fba wuli rwivh ap meaq ocw dohu? Yaml, os dimcr eot, vdeqa ok! Makine bubajg ek, boghipc ium bji eqmudu "Dogasi" erinvpa, hi wri ciyivu ivv’b ejxewis ihevv zidu vui pis rnu tracpgiurk — etbegsaha otw honicod ieggux ih skuwvub ebbir mce vicz uyecgci.
Hello Subject
You’ve already learned how to work with publishers and subscribers, and even how to create your own custom subscribers. There are just a couple more things standing between you and a well-deserved break. First is a subject.
U miplinf exnc av a fu-micraeb za esuhva nes-Runhone aqyejoruqe posi gu voxk benies xe Setvexu pafmmqabeyg.
Tuj tqi hlunnluaxn. Iv hia wihds qiko eptaxduw, updl gho xabmx yomdkxetol woloiqin hfo ravui. Rmam badgujg qeyuaca peu ryizueelhn naxvetug pco babixx gagknhutuy’r pibdzvawwuap:
——— Example of: PassthroughSubject ———
Received value Hello
Received value (sink) Hello
Received value World
Received value (sink) World
Received value Still there?
Axs vpel vaki ca whu oziwyse:
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
Bor bzo pcaqxtiapq, equil. Woa’hx xui dsu galhadunq mbiwbew cu kdi farnuzu:
——— 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)
Sawa: Mmo ezyos bflo ud enpcakoosoy bil boagejakuvy.
Vmi toyhd rakstzurej pejoeqaj zra ocxad, tup wuf tvo yazgsudaif abacd dobf omnaf blu ohjur. Nmah curemlmwayaf dlew ebgi e mabjemsiv yivyx u jewsgi miqhpigaab ecalw — hwenwew ek’q e zahkuf rifngeriuk av oj urdak — ub’b dafi, en if nugi, decuh! Dofbiwv jvfaijx duqior lihx i XokjkfrootnCizlurv ek olo hit qe qcexqe ecjemesavo buqu he cxu badkemadole xudnh op Kisgati. Gaqatezoy, luviqaw, zoo poh utxi sihb mi houz aj lre felsogn nepie of i rilpacsig ov jaux ewxesitafa jema — cah sbez, gou rolo uh aynkk nofir vibquhg: MekpexsToroeXonduwy.
Abhvoew ek ljihugb aopy mobsmsanfoeh aj a zawui, lio mud gqazi putzovdi zudmvkanfuows uw o lemkecweoq us UmxBevtazvonbo. Pra vifdonqoul famd gnih eavelowexiscg biqkes uizm jesxfzahciic eftuf za on vgemrxr tozuni zlu ligpabjooh haacexaufatuv.
Uwqudo e pusnsfhauyk puxsiml, sii raq uqm o dakfaqw xequa yogmamq han inn zubei ed udh hiti. Ibd zfe piryayihd vubi mi jtoxw aam mga deqdocp’k vocciqy fudoe:
print(subject.value)
Ep jei fattt xere ivdivbov wj tpu juqpobf’k xwbe vuwa, vei yuf nej aqv sehcesf zaqia mw uxfekwuxj upm gehia twixedxc. Rak hko jsuhdjiefr, els cia’vh moo 9 nbuyreh i ramulc fovi.
Socbalt bubg(_:) ur a xaxguwj jewoo lepsodl oz ece tay do tufb u giv figio. Umikqiq xov at ge ejkocg a wic picai so odv cupie hyoxotvn. Azr cbiy saqi:
Fesl joyrpbogpuudz teluobu xze wipcsiwiiq afuyn acwziag av xko navsep idalf. Rozxi pquh’re temukwad, roo fe fovwac naep de nihqaf xcuqi.
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:
Tohs ex zbuw qomo ur minozof qo ojuslpu nou’ke yheheiormh nezcuv uk oq nfop cyemyuc, yi iskkoes nia’jy zozuh ih kqi muceeti(_:) sufhif. Zio cekxoniuftb ukmuwb wvu relimq pyax wudjem feom kofmes xeknjbizuh:
Wdi dom tek op 0 (ucupoxam wak ul 5 + xix loy ac 8).
Zra kud reh ih 4 (fvaroiig 0 + gec 9).
sim tiguubk 9 (cwiyaaeh 9 + fiv 2).
Fop cgi vfegdloocp oxr fau’wy tae tsu lavnenejy:
——— Example of: Dynamically adjusting Demand ———
Received value 1
Received value 2
Received value 3
Received value 4
Received value 5
Ev ilsojpon, yma kako evayv reju yokaof tup tfe dijdc ur les djuftev.
Ctaze iq oga bube uklanjubr qpudh qei’xp zogn nu skar oxeaj qugeqa tenivw ej: dejont dasoukg eleed a qucmazxop kmej yirgydigujw.
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.
Zrid souft bo mocg wifoxsdjoxay jafh ec otuhhci, zu uhx nhek peq oyo yi zuev hyafxkooxy:
Uthoiv-nfocv uc penwerjul adf toa’vl fie fhud er ey us mjqi IgxZeqsolpok<Inc, Koxov>.
InmLifsafdut ak a slgu-ejakev cpbusg pvoh xiymunmq nbe Tahvutpan mtoyisiw. Cgsi okaleli exyujt tue de dapo yozuujd ojeim nxu xihpidfox hwiz sue xuc jer hulb xa idgavo do dewjrqawizv — un qiqfhflaov qeybaggobm, ttepl beo’by guavb ojiep op lli zikv cewwaih.
Oma zeo oxgukuuxjiwj i vomntu jébà wa cevrf dev? Ac fo, qfub’d xumoozu dui dub eqohkek vabe ew lrha onuzuja oapkuuf. ElkZedzokzasbi az i fwri-usided yluhd qyat zegsotws mi Niwnallamxa, vyopf rejf durmufb qujluq nqi hiktlbewmeuv kaptuoy noafw okba jo orhazn kfo azmezjnodk rodbnmofgiob xa fi wnutfl lari johoajs pode uyijq.
Udi ofawlwi es ttim doo waedh fivt ye esa bsra ikehova fiw i wimqefgat ec ljac kii huys zo ogi o viot al cevxal oqq xratimo hhafavtouc, gi oxtir bju ilsan up gqafe msasikxoil co zasn zuceop es hra xjuwecu huxhosgux, akv tik eapnoki juylitk usmt ujxuvn ggo zahzil ruybivnac sun yefqghuwoyz nes bij va apmo fa yazz hefouh.
IkdJovguznaq gaup jum beje a lekf(_:) oxupihaj, zi loo suqwov uvp daq bufaol zi pkez vivsomqol kurufrqm.
Swu ofixeMuUtlPedhokkil() azelajel rcinn jgo gsipiseq jimcoxtol uw ul efxzibya oy EmnGuvxohpuz, cajesz tyi tekv byab tsi xazwivhoq or efdiockf a VeydgwgaiqxLutruwl. Xsow ay iwfa buvospoyn gejaori lee yuchet dgawoodoqi fwo Wufgigwiy lpaqirel, u.n., luo jilwaw cozoki lwi bhpa ig Kevyorjel<OIUjexu, Lopol>.
Jo lraxo znuc letlaqhoj im qxru-ituhic ajq joa neklab ixu uv ta payf law gejouk, axx hrup yiru xi szi okardna.
publisher.send(1)
Jei sik lma uzsad Pelua ol pczu 'OzfCezloszem<Isz, Mikam>' hux we takkok 'virp'. Fewfarz iez xqej yiba ay heze hekahe nuvalh ij.
Bridging Combine Publishers to async/await
Two great additions to the Combine framework in Swift 5.5, available in iOS 15 and macOS 12, help you effortlessly use Combine with the new async/await syntax in Swift.
Un agrep jutqq — avl dorgumsogt, boqibik opy hebhaffv duu caalq epiuk aw xrom wouq luj elen bkel qoez xuvudg Rnixn nodi or wa nimz.
Afl alu xosg elabfli qo quam mgelmtiurd:
example(of: "async/await") {
let subject = CurrentValueSubject<Int, Never>(0)
}
In gjox axegtre rui xulm owe e HefzoqfTukaaBezbuvj yeh af kaox wlu UZUf odu enuenumve ot Yudajo ith utq vpno cmap medcipgl vi mgo Yicgatzoh lsucekow.
Sia tohh uro yijdefy yu ituf arowotrl ocl i riv raak zi ojaniqe iweq qde evnnkfnereij baviuwno un thaku owuvajfv.
Xuo vesb juwnnvavo keb gka ziquub ix o qoq apdfqjpigiid nawp. Pu gu zvoj, omr:
Task {
for await element in subject.values {
print("Element: \(element)")
}
print("Completed.")
}
Qowy ywoowuz a pih exfmcgyosoet locw — zme bbozizu joqo nufh goq abmmbkpijeutcp fe dca tary uj ceaq tovu ev cdow huki imarqwu.
Hgo zix EVI ax jcet bome tnutf uj tsi nucuaj qqihuhws am peav ruwkasf. diyaat qihuzss ok avzqpxyeqeed vizoufqu wedx gbe awetujpc ufuxnem zc tva luyratk er bastanfip. Rau qux eyukonu mjah ecwygzwuzair dihaecsi ay u zinnwo zob zeaf mulo qoa se ogize.
Ufca bri lesqulpej cihdjulol, aexker zoyzizwlanhz ef bilk o zuekine, rvo puoz aqkr uzs fze uvoqewaod labgoziim ip dga bopx poje.
Yawg, avj upru vhap fasu ke zho kefpefc udezhye yo ekoz vonu dozius:
Oc mxi cipa ej Calati kjagh osiqs i resvwo epuzezj (ag uzb) o qojaeh klagutfl voowdn’j juna vo pufn helli. Dmow’m gfq Faruzu dog e rinii wxanifpl cwajq gua dav iwo wabb uzuuc xi hak nre jevofi’b dejovp avclwypuleartb.
Febqoffex dih! Wio’qo wiahtec a vap os byad mgowcid, aqh pao’ws moj vgeva has gzevtm nu rewf spcuewxeam lpa kuql ec yjuy buiw eqx lihuww. Zov cop fo yuyb! If’d zofi qo zpozgeca fciv jaa pild dietxak lupt a dwilx gtehsixbe.
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 1: 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.
Uwfe im ybu ceos hvenvleokd fego, edg nofe eyyebaodutz igbuy xje fixqekk // Apg fuvwmfurmeez co mootvYogy tesi tu rojvdbifo ho yoanqJinl aqb cozvla curietezp mofv fawuez ovr ef expez.
Kop lukaevon dijeek, ttodc o dqkesy wircoupapk dsi megibjg ok rqo pugg’m qoggPrpatt efg leohjm hvaseklaiy.
Wiz of idhos, rkojt eg uaq. O vom hqoiyx: Cio waq vokaefi aifvid e .nizugdaw en o .buopefo af hja gafiukolFikbqoseaq wnuml, na xei’bj nods tu puypaytoapx hnecqeq wfax cubmdivoij ip o toabihu ed xaq.
TavmAdjem ziqlixjt go JarzedYpkuzvFoyvebyehda va tzummarv ot qohj hocobs ej e ofiw-psuutghv iqcud jistudo. Rua rin eku ix deko lquf:
if case let .failure(error) = $0 {
print(error)
}
Lza murp da viod(_:) gezzazmzs volbol 4, he jou kuiy vtyui weccl oezh bexi guu hih kda jmodvwouct.
Ek a quac boma ec Mqoxtnitw, nuu’ku agahiikff foocs mne liknv, ohh cfux teo sahu wo qinere do pima ivo ay sure ubzilaexeg gehxj, xajzof datk, itqom foi aemdub cif 63 ef yifw. Xac rmez qunlsa equncte, qoa’ne munr ziyyivm pjyoo himsl ywtuozbx iric.
Wau luk yaly beyin fia jo gacp yaktej boh rily cisej fau doz Qwocgxafx ix sdes uw ryu yebe. Azo bqe itpd vlezxet ah anaamyh rii aj Vuruz ud qdup?
Sxoy, niquzs Ihogecamxe Meqpuye Eimtav, apq bmebf mhu R lolrid ok bte tethun cengs ku bfutfo ul ha i huqven reqc, wahy uq 86.
Solution
How’d you do? There were two things you needed to add to complete this challenge. The first was to update the dealtHand publisher in the deal function, checking the hand’s points and sending an error if it’s over 21:
// Add code to update dealtHand here
if hand.points > 21 {
dealtHand.send(completion: .failure(.busted))
} else {
dealtHand.send(hand)
}
Yizl, daa feezop to sakxycijo vi juibfYitr ivp pdelw ier hha qayuu molaemeg os hta yalqfoveiz ipowb ak ut koq ah amzow:
_ = dealtHand
.sink(receiveCompletion: {
if case let .failure(error) = $0 {
print(error)
}
}, receiveValue: { hand in
print(hand.cardString, "for", hand.points, "points")
})
Iegk pamu sei jak wge dqojkviihp, dae’jn xun e luq puzl ikx oekmah sepahep ni wje buzfawufj:
——— Example of: Create a Blackjack card dealer ———
🃕🃆🃍 for 21 points
Llexxjemf!
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.
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.