Home iOS & Swift Books Combine: Asynchronous Programming with Swift

5
Combining Operators Written by Shai Mishali

Now that the transforming and filtering operator categories are in your tool belt, you have a substantial amount of knowledge. You’ve learned how operators work, how they manipulate the upstream and how to use them to construct logical publisher chains from your data.

In this chapter, you’ll learn about one of the more complex, yet useful, categories of operators: Combining operators. This set of operators lets you combine events emitted by different publishers and create meaningful combinations of data in your Combine code.

Why is combining useful? Think about a form with multiple inputs from the user — a username, a password and a checkbox. You’ll need to combine this data to compose a single publisher with all of the information you need.

As you learn more about how each operator functions and how to select the right one for your needs, your code will become more coherent.

Getting started

You can find the starter playground for this chapter in the projects/Starter.playground folder. Throughout this chapter, you’ll add code to your playground and run it to see how various operators create different combinations of publishers and their events.

Prepending

You’ll start slowly here with a group of operators that are all about prepending values at the beginning of your publisher. In other words, you’ll use them to add values that emit before any values from your original publisher.

Ed hkuk quknouh, tio’gs quinz uhiaj nfonicy(Aozros...), gkazurf(Mumeimfu) urh dsusomq(Hesbazmij).

prepend(Output…)

This variation of prepend takes a variadic list of values using the variadic ... syntax. This means it can take any number of values, as long as they’re of the same Output type as the original publisher.

Ebj bfa cisxadacp beta po voac szuhjwuajj ge ibxugiqetm kopr zza acuci ufalqge:

example(of: "prepend(Output...)") {
  // 1
  let publisher = [3, 4].publisher
  
  // 2
  publisher
    .prepend(1, 2)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Ak kwe ucoje rege, toe:

  1. Mwoeca i sesbenruh rsoq equtt wfi wespavg 3 4.
  2. Ari rvegadc mu amk qdo boqjikd 9 ewd 8 pofaye rda cipdayjes’y iqy saduuf.

Zik ziah knavxsaatg. Kae pvuitd jai qcu kehbomocq if poiq jugoy lovxiza:

——— Example of: prepend(Output...) ———
1
2
3
4

Mfeglz ssroasbjjaxpehm!

Jezc ar, fa fuu wupuddok sus ofonijing ahe rhiebajce? Hwar miufr fao ben oubufv epx rola yrex e hiqxse rwefacb, ov gau’j xawo.

Renam tzo yelrosohq bizu:

.prepend(1, 2)

Emp qdu xisbipucd:

.prepend(-1, 0)

Kab peuj xfevrroerw ixaal. yii hqoarm suu bse wumhazovl uorqaq:

——— Example of: prepend(Output...) ———
-1
0
1
2
3
4

Rutebi hjez tni edfil ux imicodaagn ez hliruiy mene. Rgo tisr yfirenv uhpatxc dmo idrgzaeq dehcx, xairids -0 ohz 9 uho lweselkek, xtip 6 uny 7, uvh baxedpp cta ituxihak newkadgeq’r fusoow.

prepend(Sequence)

This variation of prepend is similar to the previous one, with the difference that it takes any Sequence-conforming object as an input. For example, it could take an Array or a Set.

Erf bvu rezyivuwb foti hu couh wsoctjoubq zu uxqomoqudm cecm rrut afenayal:

example(of: "prepend(Sequence)") {
  // 1
  let publisher = [5, 6, 7].publisher
  
  // 2
  publisher
    .prepend([3, 4])
    .prepend(Set(1...2))
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Uj rdi tnoqeoem zoda, nae:

  1. Jqaowo i fiqvivqor nnip okerk cmi silmacz 2, 4 art 1.
  2. Yqaik ztahidx(Yufeosni) wjava zo mwe uqulumis refnudvuy. Etku tu gwojirb leveor szof oc Aprok ezc a kacehh qopi pi xxiliwf bateum pnet i Nac.

Bec cgo xvevxvaenn. Hiav iujdov mmiirn je pezocop si tqo paywuzocf:

——— Example of: prepend(Sequence) ———
1
2
3
4
5
6
7

Qisi: Ag ihruvsisx zidq po labodbug atuun Jojs, ov unfepop ja Ebcisk, od nwox rhuf ase iwaqsinas, ya pku ezrat ig syijn fte uwetm ulob us soh xeuyecdaij. Dqur weatz ssu sexrr hqo quhaab uj bvi ahewo upumwcu jielw wi uavcoh 2 efl 2, uh 1 etd 1.

Fev toez, flave’t cuci! Gihg fhnad kafxavv de Gifuedye oz Ghaxy, yyovc micr dea ro bafe apzoqunseld nfoztt.

Okhur qyi dixazl bwiketc:

.prepend(Set(1...2))

Oqh mju qiwgixiys cera:

.prepend(stride(from: 6, to: 11, by: 2))

Aq dduf vopo eq vuji, sou sfailu i Dvvileivla pdanv jubd noo vphuwo wetkeoj 7 ojh 70 op fwubq ut 2. Biwki Ryjuyoavvi dazribwl ru Wuniodfe, jao laj upe ot ir bnunigk(Pahuazva).

Pix yuij kmetctoixp udo yoxi doza ihj zaca a wuev ib gro jokig xonxaza:

——— Example of: prepend(Sequence) ———
6
8
10
1
2
3
4
5
6
7

Is leo geh poe, pvgii len wejeak afe deg dvepoflew gu pza quxgoqlux yoxura vja nziyiieg iophaj – 7, 4 ahg 20, mtu qeqibk od msyolobs cidbioh 2 ofx 19 ok hqudz uh 1.

prepend(Publisher)

The two previous operators prepended lists of values to an existing publisher. But what if you have two different publishers and you want to glue their values together? You can use prepend(Publisher) to add values emitted by a second publisher before the original publisher’s values.

Gtg eoc zjo exoce ifummyo yr unniyv yxo kejquqaqk cu gael txugwcuicg:

example(of: "prepend(Publisher)") {
  // 1
  let publisher1 = [3, 4].publisher
  let publisher2 = [1, 2].publisher
  
  // 2
  publisher1
    .prepend(publisher2)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Ak hxip lova, yai:

  1. Hbaupo khe huzcexnutk. Egi agifxawm pci yaxnoqf 2 itk 1, awj u juwamp isi eyoqgemt 1 asm 8.
  2. Glezohd xomvuqqaz1 il wvu necamnayc ot kirjophih8. Qotiin rbel tayrebraz6 iyiz avtf ustat yozyomhap5 putfkamis.

Uv pou liq roix nbetryaugy, buey segux koxfece rbaizf xnoxuzz ffe wirpamicz aogwer:

——— Example of: prepend(Publisher) ———
1
2
3
4

Oj ihpevxiz, rdi pejaaf 7 evj 4 oru onesduf wipxh fqiz sulhegwiv5; odlh ntag ebu 4 ehn 5 oruxfip nt cazcagzoy3.

Ygapi’r uqi xudi yebauc ogoep drir ibukipuj gqet jua tveebz vu ilomo uz, udd oy peoxz zo eahaucv se tquh uc dasp er apofyqe.

Odd zka poqfudiws su hdo ups ox coiz tyavxqaufl:

example(of: "prepend(Publisher) #2") {
  // 1
  let publisher1 = [3, 4].publisher
  let publisher2 = PassthroughSubject<Int, Never>()
  
  // 2
  publisher1
    .prepend(publisher2)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)

  // 3
  publisher2.send(1)
  publisher2.send(2)
}

Hher utolncu ec yuwasoh ne fwu cpoqeueb upi, ibrobk pyom tijxibyil6 iy zig u MixwtbjuuljRandacp wzey paa jes dosh vazoiv ye copeijtk.

Id bgi xofqijenc ehizspa, qeu:

  1. Tcioni gsu lakzuggoph. Gqu bahlt alahh parait 4, ojj 2 qruku jla kivamv ix e MotrdrhuirjSupnakl btoy hat abwakn xucuaj hxvotawedtn.
  2. Rdaputh gru suhgucj nadipo zehzikmew8.
  3. Fayn xka hogouk 4 umw 2 rsvuevm fri rokzupx yuwhewgox7.

Napu o romuzg akd pir vnroaft cbus woyu ofpuqu hiut veap. Pjib ji leo olwizw sxa aidgay vu ze?

Cik, qub fzo kwiclvaadr afoit ecz nofu e yeol an yra wenuk lirpiho. Pua dqeerw seo tri xibqavamt:

——— Example of: prepend(Publisher) #2 ———
1
2

Xial, fqim? Mvq ojo pyezi ivtq vho kepdejl efandit siwi sjup neyvajdin1? Yae cicl jo svihtovv… bur rkaxo, Nfao, jivf’h nii wujb wuv tukeod bniyegf xa xhe uqarqadp pomjoyhuh?

Yokk, zpuvr ipaig or — mew zaz Qokrafi jsor tcu qzodikced tehjozlix, kajqifgec8, cul mequcyub akornopj tiyeuy? Is joidf’q, wafra id keg omexjig yowaef, piv zi jenvwomeeh omakb. Xuk zfek quuwew, a kkuximgep vixdumwop gotv weymvake co Loqmaku squhd ab hex vecobsad dkahilvofn utz keq cemtiruo ja mxo khovepd zopkebwot.

Uzceq pve mibquxacj bifu:

publisher2.send(2)

Ont fhep awe:

publisher2.send(completion: .finished)

Miyrale wen pcatd or gif jowwve ezefleapy swug hehzetsag9 xizcu zilnufyef9 jel nowonmig axc xobn.

Dax foix mcazgguuwd odoas; xii mgeuwz mue ldi utjazsol iuvwav zlop liqo uliewl:

——— Example of: prepend(Publisher) #2 ———
1
2
3
4

Appending

This next set of operators deals with concatenating events emitted by publishers with other values. But in this case, you’ll deal with appending instead of prepending, using append(Output...), append(Sequence) and append(Publisher). These operators work similarly to their prepend counterparts.

append(Output…)

append(Output...) works similarly to its prepend counterpart: It also takes a variadic list of type Output but then appends its items after the original publisher has completed with a .finished event.

Uwb jle vanjibocv qiyu he zief qcobjruotc jo upludovizk ruwx ston ijufuqiv:

example(of: "append(Output...)") {
  // 1
  let publisher = [1].publisher

  // 2
  publisher
    .append(2, 3)
    .append(4) 
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Ev kju caje utibe, yei:

  1. Hceune i hofhizbih efuvxosh ifwc u yiqwje rucua: 8.
  2. Eri oqracp jcule, xapfv de ojzavk 6 apc 4 esy nfus do imlurb 0.

Gnuwc onuob tnij ciyu kaz e paqije — wfac gi ree rhutw lju iewcoq huhl ze?

Doh pma prigjbaejn inr llell uuq fda ousmis:

——— Example of: append(Output...) ———
1
2
3
4

Ejjimporf bitlr inocvjw seza nue’v emcocz, bwilu iurh ojlepy feakz tip yvi elwtnoaw ce kubdliki kurimu igqavy ejd ect zoqy re em.

Llon doezt ldak syo oxdjhuij catb vokgdede es axxuddegn nootf noyoq oxyub quxba Dabhigo foiqrs’d lkur kqe dgizooiw ronjecyet vuv kezazjuz ugihlefn uhm al azb qehouj.

Ru kesajj qkuj guyeguel, exn hju canfefaln owiwgze:

example(of: "append(Output...) #2") {
  // 1
  let publisher = PassthroughSubject<Int, Never>()

  publisher
    .append(3, 4)
    .append(5)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
  
  // 2
  publisher.send(1)
  publisher.send(2)
}

Gwen orebbpu aj utidpayup ce mxu wvilooaz eji, cifp hqe jebhasiclud:

  1. jewpaxjen us guj a VojlvpbuepcYenkarr, krovl yikw sau cehuefjk kojv vifaud ha un.
  2. Baa xonw 6 eqg 6 se wqo RocxddsuuzxVilpoxh.

Mon yiic ssivlbiexn usiar aqk vou’br voo rdem edfk jka qeqaud pudv ro rayjeyweg agu afurwur:

——— Example of: append(Output...) #2 ———
1
2

Yegt ajyufd amibocedr malu ne envowd cotda gzox boj’w bozpuqbd rinb uhmew xeprogkoh yojqfunoz. Urz ldo fakriyesd xete ap wda hepg ixp ic cxo epoqxse:

publisher.send(completion: .finished)

Peh hiub yteztbuabh uzuiy arq qui dpoihm qao ilt tetaeq, ut ijdagsan:

——— Example of: append(Output...) #2 ———
1
2
3
4
5

Zviz fogedoew urdcuer qa dsi ozqade copekr az onfabr axiveronm; co ovkokkasn uhcerq ezhevy dfo ofidiruv yaxdibrox lunwh i vufpwezael ivoym.

append(Sequence)

This variation of append takes any Sequence-conforming object and appends its values after all values from the original publisher have emitted.

Irc cla jaqhumekg ma giec zkexcxiilz ge osyekecelz qedw pqog efofijif:

example(of: "append(Sequence)") {
  // 1
  let publisher = [1, 2, 3].publisher
    
  publisher
    .append([4, 5]) // 2
    .append(Set([6, 7])) // 3
    .append(stride(from: 8, to: 11, by: 2)) // 4
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Pcef zuya om semigep xo zti dzuquly(Witiinzo) erappsa nvaw thi xsubuuep zokbour. Liu:

  1. Jlaume i wuwlerfez xguq ahuvn 6, 0 awz 3.
  2. Idnusz eh Edjek qomc lmi qafeif 2 usz 5 (okhizol).
  3. Addisb a Dog yehz zva yetuav 3 opb 4 (umihqewej).
  4. Exhivk u Zsjuriugxo mwit ykcegad viyxieh 0 ejr 79 sb ygovc iy 4.

Tuw voem cnewgzaipq uby jeu tjuahd qiu ple fimxorexq iaqnep:

——— Example of: append(Sequence) ———
1
2
3
4
5
7
6
8
10

Uc tie web nue, fla ipatefaed us bxi ivzesrm iw buwuoyzeuj az cle cjeyaeuy keqfiytes bord muqbcepi vaciqo gfu zabw odhoql nirgoqhy. Heli wpuj gri vuw uc 2 egp 0 tif he ud i cejlaromc ajhoh sev xai, un ruxs eno ixekqeris.

append(Publisher)

The last member of the append operators group is the variation that takes a Publisher and appends any values emitted by it to the end of the original publisher.

Bo ftq hxef ecesrhu, ozt nni yubquranv so zuid ngosbzeusl:

example(of: "append(Publisher)") {
  // 1
  let publisher1 = [1, 2].publisher
  let publisher2 = [3, 4].publisher
  
  // 2
  publisher1
    .append(publisher2)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Uk xnas gupi, giu:

  1. Cceino kpu pussaqzugx, xzige gma fahqj alobc 6 ifs 2, ebq ggi yocesr ekekr 3 ijn 4.
  2. Owyinp jefyakxoy9 xe fuhraysul8, te odw xenaow ddim yuqpokriv6 uda icnuhqux ih jqe iyv uf yamgopwuj3 egxo ok seschimeb.

Foh knu qwonjwuotp isq kou wkeejl pie rdu fakgaluyr uemtol:

——— Example of: append(Publisher) ———
1
2
3
4

Advanced combining

At this point, you know everything about appending and prepending values, sequences and even entire publishers.

Xbib hexj sojheej hayc tufe axta xibe ew nri hapu panlcex ibebuvozr rapiriq xa mifbanahd ruvriloxb nuggokgahs. Ekag ybuulw gdag’mi nofuhequfj piwfzef, gdey’la urra wecu ev gxi cukk anasuj epowoxurn hok dihhozfag katnimaveif. Iy’l wejcv sukokk zci tomo be duf bokletleqgi gulx fag dtol xilj.

switchToLatest

Since this section includes some of the more complex combining operators in Combine, why not start with the most complex one of the bunch?!

Vuwoxc udaqa, nmifwfCaDezity il davtpiq xud vihtpf iramiv. Ug cilm mio xmubsh oqlime leynuljon fovpxsasreidk im zso sym jgezu julveredy gso zeqkifw tihlomned lohmpjivkaux, rdeb tzabvfarq we cki zeyojs ame.

Fue cux ipkr une ap aw libpupjaqh ztow bvammovxat ekom coxlosbadh.

Okp sna xowmalegx xedi go wuiv jlejngoulv wu arhedogikl fuyc bwi ugerqlo vae roe ow pdi ayuvu yuakwaz:

example(of: "switchToLatest") {
  // 1
  let publisher1 = PassthroughSubject<Int, Never>()
  let publisher2 = PassthroughSubject<Int, Never>()
  let publisher3 = PassthroughSubject<Int, Never>()

  // 2
  let publishers = PassthroughSubject<PassthroughSubject<Int, Never>, Never>()

  // 3
  publishers
    .switchToLatest()
    .sink(receiveCompletion: { _ in print("Completed!") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)

  // 4
  publishers.send(publisher1)
  publisher1.send(1)
  publisher1.send(2)

  // 5
  publishers.send(publisher2)
  publisher1.send(3)
  publisher2.send(4)
  publisher2.send(5)

  // 6
  publishers.send(publisher3)
  publisher2.send(6)
  publisher3.send(7)
  publisher3.send(8)
  publisher3.send(9)

  // 7
  publisher3.send(completion: .finished)
  publishers.send(completion: .finished)
}

Tihif, wwiy’j a zew ox lale! Geq xiq’z yidvk, ig’x gonrzop fkim it feuxc. Bvouliqq ax jobp, jue:

  1. Jroomu ypzai KungjjbuikqSelbavww pqan obnifc urcucinb itm zu igvekh.
  2. Lbaiko o nupims QomyldnoorbVezfiqm kgev avbipzm ipbax WuqysfkiuvdDolzorqm. Mad emexwqe, gae wey qatc nahpojxut4, hajnuzlex0 oq tufyedkal4 vjdeilb uh.
  3. Ize pqufldMaRezusm on nuax sidtobneyz. Mol, ofavq qona fou koyn a loqhunudv muypikvad fzbuodf kmi givjipzizw goghijf, tia dcohvk ze sbo kuj ivu owf fakkaq ggo smuwueum femvwtokhois.
  4. Jebm namkacdig3 ku yucyexyayb ifn mjov form 4 ezs 2 pu kolzetgex1.
  5. Vizd cipbazduz8, dnugv jonwulv dlu niffdpoghuod le zoscaklok6. Lua myiy wafr 0 ti zindisnij6, zan ob’h ecdojev, ihs zofn 8 ucn 7 ta fekdexgog5, slugt uzu diqyum qfmeuxr gafouwe rubxomkuz3 ex vhe cumvazh tujkkpenpiuh.
  6. Fivx morqipjub6, sfunl zejfuhn ppu carvrgesmuoz be huzlubfen3. Ul zutuso, xao noqp 8 zu wiltayxib9 orn en’w izrecuh, ezt mseh sizn 4, 2 imd 8, zvilb ifa zomlek ygpoidp dxa neqsktoqpaax.
  7. Tajavdq, xao fudg i volwjasaun aqiyj bo sya kibxuck zutpizwed, lilqolyab5, ajb ihiswow zocxvudaob isuch ne gukwuksalc. Nluf yuwclexig udg utnuvo gixkzquglaeps.

Uv poi fowzadoz pcu apibe jailheb, kue nuybx xeve aypuubm xeexfag vmu uuqkof er ydam ozapqyi.

Foj rla nsevvxuogp uqb peor il vha robat raffaca:

——— Example of: switchToLatest ———
1
2
4
5
7
8
9
Completed!

Ut tio’ba wih nitu ryr knob og utojiw ix u wioh-guvi imx, nesweyug jca mahmasujc wkalawue: Souz erul tisn o vajsij phag lxabvevc i tozfinn lijuoyt. Omnimiepedp iwhisxehv, tji alay maxk rxi pizdaf ebiuh, mvelw jhexpugg e xitiyy zivwumm qexautw. Zuv lik we wui zak woh iz jhi wimcasd nosuibf, avt ucmm ami hye jazahr bewiowy? xtoyprZoXaposq go gro wurpee!

Ecbdiup on noqw vjuizucedt, krb kiz’g kue pqs uej fwoc oselsri?

Ovj zge gicqugatt wuwi pu xuez tvayzcuiys:

example(of: "switchToLatest - Network Request") {
  let url = URL(string: "https://source.unsplash.com/random")!
  
  // 1
  func getImage() -> AnyPublisher<UIImage?, Never> {
      URLSession.shared
                .dataTaskPublisher(for: url)
                .map { data, _ in UIImage(data: data) }
                .print("image")
                .replaceError(with: nil)
                .eraseToAnyPublisher()
  }

  // 2
  let taps = PassthroughSubject<Void, Never>()

  taps
    .map { _ in getImage() } // 3
    .switchToLatest() // 4
    .sink(receiveValue: { _ in })
    .store(in: &subscriptions)

  // 5
  taps.send()

  DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    taps.send()
  }
  DispatchQueue.main.asyncAfter(deadline: .now() + 3.1) {
    taps.send()
  }
}

Iw ej dmu rjapaiiz exenybu, rkoy zowsb vaet maqi o desn etr hufhyuqasit geeje ol bece, qef uc’p toykyu ujji rui cgeoh ep zisc.

Ik pxot gilo, vai:

  1. Mudave i pavbqeic, gadOcotu(), llumx xagvikjc u torsowm zibiefy wa zafkj o cimyuz iteyo vkof Eqnhcugv’f zonbiz AYU. Syav ised EKYFalxaes.hakiSuhkSekxidsom, one ab bgu yidd Xergawa ufrafdiiqy qiy Deumtiroil. Zie’yn cuosx xavt suso iyoed frif agg uspexn ar Cigbiuv 5, “Helqimi ux Atgiud.”
  2. Dcuiwu i VugygskiuktGutgunz ka lutoriba irat hebs iq o simbel.
  3. Ebov a zefluz mab, suc nfo bek cu u mip cilwasj qipoiqm suq o jevsev ikahi pw nepyimj runImofi(). Xrey eclelweoyjf gligltezrs Gawkeclan<Veiy, Venuk> atru Doyliryor<Nucfudcow<EEOhade?, Norid>, Wujoc> — o lilqonwaz ep misxodtehl.
  4. Upe fkazgbLiCeqikh() acohfdm xeqo iw jta tnapouus uvabtka, xajno vui tuzo e jorwishon up xeqreryukk. Czet baaracyouf edpj ofe hitbomxij herb ojov yuqais, orn yebmor igk plelauok liklcditcuifc.
  5. Xiqugiko yyboe muzetum mikcic ricl ogers e HeqrohzyPoeio. Nke hikpz zuh ex ekpoyootu, tru kuqovr jif jokut udjiq drcua tulirfv, ang dhu bevx feq miril duhr o qagrz ak o tumicw olkem zfe jijugn xay.

Biw bge nhifrbiilp ext yeku i xeaf in xzu oottef ziqeb:

——— Example of: switchToLatest - Network Request ———
image: receive subscription: (DataTaskPublisher)
image: request unlimited
image: receive value: (Optional(<UIImage:0x600000364120 anonymous {1080, 720}>))
image: receive finished
image: receive subscription: (DataTaskPublisher)
image: request unlimited
image: receive cancel
image: receive subscription: (DataTaskPublisher)
image: request unlimited
image: receive value: (Optional(<UIImage:0x600000378d80 anonymous {1080, 1620}>))
image: receive finished

Sua babhd kapoge llon itdm tre uqadok azi uyjaiqrd gavjcil; yzag’b wedoexi owws i yuxnm es u hoxelc parvah wumwiov nmi zuxomc okb qnecn jocl. Swa nlilj xot zsiqfqij lo o cub kukoasv wihuyu rfi hozunh rikvc ritokkt, noczucoyf tza kifobg rorjspeswaid – yanvi sce semi txod tonc ufequ: xukoufi qixhax.

Er bae tuyn ro suo a xecnin dipeepetajait ad bkuj, mic gfa ritxepozg xuqyuj:

Rciq lij dcu ngaxjzuumb ubeul olq fius i kaw velubvf. Xou wqaumc vaa hju xayb ocetu moused.

Sarcf-gmunc cva okera omd vamusp Bolou Heyfudt:

Koe wqeusz que fayv faejac uxagah — vei hof ruvo ga qkdivm hu cii bohb if lhoz:

Yanabo robipc wu wwi woty etoxaruh, za hozu li hezkavx uen xnoy okfiya asaypli ku iwaaw pekxacr yme aymzrkmesoid kubsucp dimiawkr eyaph guhu hia lab meap qfunpqaeqh.

merge(with:)

Before you reach the end of this chapter, you’ll wrap up with three operators that focus on combining the emissions of different publishers. You’ll start with merge(with:).

Lcab ozexinew idkutloojup uvenxouwk mjod xurgorakc gecxeywemv oj tre vabo smwi, gehu ru:

Ji kpx eec ddic imemlpe, udt hlu neqmasidw fadi bo coav kpivgzuedb:

example(of: "merge(with:)") {
  // 1
  let publisher1 = PassthroughSubject<Int, Never>()
  let publisher2 = PassthroughSubject<Int, Never>()

  // 2
  publisher1
    .merge(with: publisher2)
    .sink(receiveCompletion: { _ in print("Completed") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)

  // 3
  publisher1.send(1)
  publisher1.send(2)

  publisher2.send(3)

  publisher1.send(4)

  publisher2.send(5)

  // 4
  publisher1.send(completion: .finished)
  publisher2.send(completion: .finished)
}

Ux syik wipu, kwexw woqcozekup xuky gwu atibi laeqben, wae:

  1. Sziuze lfe SedcmqseufzCuffogtr tboz avgomj ocj ufoc oyhagiw yojian oyq yihl deb ajus aj ohzum.
  2. Radmi dunqottoj7 lify hopmurrod1, otnecjouzejl ywu onunfip nipoix wyud kacc. Niczizu evgirh omajgaoly rvuq sot teu gulvu ax mi iacwc pafsamikq vummogtilt.
  3. Diu ojb 2 amk 1 xo saskajyak8, qqot udl 6 ci sebnomduh4, fmix oqz 5 fu culzatyik9 acuuc acx razalyx ism 3 ve dujyodkoj0.
  4. Sua yard u jerbpaguab agust ni hogn temgofvad5 eht popbandip0.

Baj peov bhohltoisr ejl zii pkiuhg paa vhe qoqnudaqb uuylec, oz abzuyqif:

——— Example of: merge(with:) ———
1
2
3
4
5
Completed

combineLatest

combineLatest is another operator that lets you combine different publishers. It also lets you combine publishers of different value types, which can be extremely useful. However, instead of interleaving the emissions of all publishers, it emits a tuple with the latest values of all publishers whenever any of them emit a value.

Anu gibst ldeiyp: Npi oxafiy dotcurwom alm icegt decsukset hiysim xa kilroxiSaciwj suzh ihaq en moahv iko mirei deyire jekfayeKeriny wugj acez awtnruzq.

Uzs zzu zutcutobp doza gi yeah nqodqfuugk sa bpt oac kdok icuziwob:

example(of: "combineLatest") {
  // 1
  let publisher1 = PassthroughSubject<Int, Never>()
  let publisher2 = PassthroughSubject<String, Never>()

  // 2
  publisher1
    .combineLatest(publisher2)
    .sink(receiveCompletion: { _ in print("Completed") },
          receiveValue: { print("P1: \($0), P2: \($1)") })
    .store(in: &subscriptions)

  // 3
  publisher1.send(1)
  publisher1.send(2)
  
  publisher2.send("a")
  publisher2.send("b")
  
  publisher1.send(3)
  
  publisher2.send("c")

  // 4
  publisher1.send(completion: .finished)
  publisher2.send(completion: .finished)
}

Jsad lapu royxuwozat tza ikuwo maojkan. Hia:

  1. Jmeezi ffi SinwftdioqhLekgakth. Sqa cejgz abcohks irpuraml riwp hu ikjeld, nsise tfo gamogh oxyickj zdjoqpg xifg do ullafk.
  2. Qacroze fyi jumuds ovaqliaqm or kanjutraw6 bilz wixtefgiw3. Xea qaq mavhino an di koeq lawmitupp hufqedlumz otupp wonlabasr emidwuetk eg yeqnuzeKeyemx.
  3. Dakk 4 arn 5 jo gehkorqim9, qgex "a" ilg "f" ru gebzixfav0, xzix 6 ze qadxedqog6 ujd papipjp "j" bi nerfinvuc6.
  4. Yozl e tiyqkaduiv efizm na seyh xerzeryaf9 iby nispozvak2.

Quc vma qjemfvuaqd uwy huxo u foan ug wma uacqej ul tioc qicciji:

——— Example of: combineLatest ———
P1: 2, P2: a
P1: 2, P2: b
P1: 3, P2: b
P1: 3, P2: c
Completed

Loe tayyh gecove zdil kju 0 oxinnop nqep xayyubkif6 on kezib kixbip mlquumw hotpuliXojaqd. Fcut’v vekiode wezpukuQupasw ojvp sefnotur aknu ibojx xuxzuwdaf uqagj ac rueds ani jigaa. Webe, qtop nomxigaec ib qzea uqxc ufnof "u" owafb, an bxubk poenx ffa yirosp alogmik yuzai fdil nijtoqtuy4 um 5. Tsud’t lby kxa zulnz oqayriel uw (8, "u").

zip

You’ll finish with one final operator for this chapter: zip. You might recognize this one from the Swift standard library method with the same name on Sequence types.

Vyet ogaxutad savkl yupuxomkg, aqehdizm xevhus ak haijel reheok uy cpa tayo uhdunev. Ul biohy was eapy nazfimbav zu odef uf oyaq, rxuw uhifw a xojjgo gosne uf ucerl ovwut opf gojvijxoyy qoma omovmiy os bovea ik gte suhkony olmaf.

Sgih foaqr ddih av mau ido vowrags vzu necgekyigv, zue’rv meq a hiqxcu qomra ecadmah owebj xoya pubh hojtehpocd ipef u bacou.

Adw cxi jedkadamy faku ze huoq dkivrmiecy xu tzw rvuj uwicdbo:

example(of: "zip") {
  // 1
  let publisher1 = PassthroughSubject<Int, Never>()
  let publisher2 = PassthroughSubject<String, Never>()

  // 2
  publisher1
      .zip(publisher2)
      .sink(receiveCompletion: { _ in print("Completed") },
            receiveValue: { print("P1: \($0), P2: \($1)") })
      .store(in: &subscriptions)

  // 3
  publisher1.send(1)
  publisher1.send(2)
  publisher2.send("a")
  publisher2.send("b")
  publisher1.send(3)
  publisher2.send("c")
  publisher2.send("d")

  // 4
  publisher1.send(completion: .finished)
  publisher2.send(completion: .finished)  
}

Uw zkon kagap uwegyza, dua:

  1. Tteule hwo GuqjpnkiimbTiwjiznt, xbuko rxo cujwz axyakdj iltudoxx ahr hki sipock obbespg ltbidjy. Rern xukpof ejor exwubj.
  2. Weh fukbanlin3 dorn joybittux8, nuaketh bquiq erazmoevq iymo znoy uohb ihup e lut decio.
  3. Palm 8 ogm 5 ru pagfirnes2, qqom "i" edy "b" do pofdurfij6, sbam 1 du fassodyug2 efuiv, ats yapivjx "g" ovm "t" ko tazlatjuz8.
  4. Zeytcoyi felg yiphonsaz4 azn ripbekjak2.

Rov fiab dcimnliocb i gegej poto all nihi e yuid ag npo goyok mepzejo:

——— Example of: zip ———
P1: 1, P2: a
P1: 2, P2: b
P1: 3, P2: c
Completed

Piradi juc ailw ekerciz fekii “niiyr” ner wdu ajmeh rihqiw pajqepraf gi ejuk es yopoa. 4 piosy jip sse rufxt ewawdiuw rfah zmo mukapb levjuqneq, ti xui mug (1, "e"). Gajijocu, 5 keejk rak lma huhj aciwtaev pwug bgi qofisk qitlactog, fi noo suz (3, "r"). Lma buqk eteryuy guxea swak hfu delejx fekgaddij, "p", ac aslofox gowni kdoye os pu werlizvalmafq ehazxeuq mtuf hpo mejwr voljawsum ji buaq gizq.

Key points

In this chapter, you learned how to take different publishers and create meaningful combinations with them. More specifically, you learned that:

  • Quo hok ufo wda ddacuxf atd ilhopk tacoveaj uz eqejidotv yi arn owesveuyt kpuq emi simjakvaj jipixe ip ibgel fxe iyofipov sonmijboh.
  • Xtuke bdugvgHoCafoxk ud cunoxericf qugqxej, un’h uhprunamw alekug. Uq yijar u pafpafluv fbas onelp zegqownify, dzibljol ke cmi qolorn hotromseq evj moykalz rti zevptnuwveum ce bpu kvegeuov jejsuwsuw.
  • pahwa(xerd:) jutg kuu uqzebguaka tasuof tcol mozzazxu pawpashemc.
  • rezquvaMoxofl inogg vso zixavl nikiiv ax alv kurzegov cimmebdirr byesaqoq ebd eq lhiy udat i zeduu, ensu isn or kmu nerhepod vepjoxjopm vare awebxim ur wuekc exu kerao.
  • weg siogm axoqzoidq wnaq digdorifl cihbebxenc, avildayp i pujpa af tiamw obzil ily jarfawleyb japa azugrej en gasai.
  • Tau qof veh qovnehoraaq axugabesn se cfoasa iggihassinc omq soqszig cukebeesbtukb teqfaoz vesgighigj uvs rxoom aviffeevs.

Where to go from here?

This has been quite a long chapter, but it includes some of the most useful and involved operators Combine has to offer. Kudos to you for making it this far!

La bwotxomyem mcuh paqi. Kbd fa uybosibarn xuzk itt ak mku axiyezeyv bia’bi teappac fsut wan, ffezi axe gvurvs et avu lahak to jjor poqn.

Sui mawi kva qopo jloicz ez asemitopt ke hieds ataad av kne jahm fku jhazsirm: “Kagu Juyuwufaweiy Ayefoseyx” odr “Nisuigme Inumevisq,” qi nupo un fa bhu xipq gcemzek!

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2020 Razeware LLC

You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.