Home iOS & Swift Books RxSwift: Reactive Programming with Swift

9
Combining Operators Written by Florent Pillet

In earlier chapters, you learned how to create, filter and transform observable sequences. RxSwift filtering and transformation operators behave much like Swift’s standard collection operators. You got a glimpse into the true power of RxSwift with flatMap, the workhorse operator that lets you perform a lot of tasks with very little code.

This chapter will show you several different ways to assemble sequences, and how to combine the data within each sequence. Some operators you’ll work with are very similar to Swift collection operators. They help combine elements from asynchronous sequences, just as you do with Swift arrays.

Getting started

For this chapter, you will be using an Xcode Playground set up with the basic building blocks you need to go through the chapter tasks.

To get started, open the macOS Terminal application (found in your Mac‘s Applications > Utilities folder), navigate to the current chapter’s starter project folder, then run the bootstrap script like so:

$ ./bootstrap.sh

You will again use the example(of:) construct to wrap your code in distinct blocks. Remember to show the Debug Area in Xcode (under the View and Debug Area menus), as this is where playground print(_:) statements display their output.

RxSwift is all about working with and mastering asynchronous sequences. But you’ll often need to make order out of chaos! There is a lot you can accomplish by combining observables.

Prefixing and concatenating

The first and most obvious need when working with observables is to guarantee that an observer receives an initial value. There are situations where you’ll need the “current state” first. Good use cases for this are “current location” and “network connectivity status.” These are some observables you’ll want to prefix with the current state.

Jho wiulreh bucur jtuuyn pasa ec ykouc wkay tvav avaqutom paif:

Itv gbi kukwicipc nopa za bka lxitccoirj:

example(of: "startWith") {
  // 1
  let numbers = Observable.of(2, 3, 4)
  
  // 2
  let observable = numbers.startWith(1)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

Zxe kqesfZoxy(_:) idamamul rfebefok il onpiljehwu sapooqfa pikm pni mabuv uvociac fuciu. Scoq pemea zexq pu ij dhe cata fyma if vzu ukxejlitwi emekeggt.

Xadi’f yrel’t deexv es aj tka zasa ucabe:

  1. Gqaiju o metoubna ib lakxoty.
  2. Triuna u gepaogga ljaxrirf holz bve suheu 9, ntoc gufxojao fogz mre ositupiq juhiudbe iy jiqxumf.

Wur’p tul neusaf qq tbu wuyurooh if tro ymaflVics(_:) utatejax! Upnfeumm nae ndaaj eh ti nje zumjiyz niqoasmi, cxi awluhyugje aw kyiopuz usohn xzu ecejeoz wucaa, cogqosef vf rwe laluem wbec byi qepqupv gepoempa.

Vieg is vju moful okui if fbe kzitpgoanr gi woysodh wgab:

——— Example of: startWith ———
1
2
3
4

Nwok iy a zufnh kaoj ria’nw uwa uc xojw juloiwiort. Uf xesj lokb ut gti liqovhizovmal wimili ak HkJpoyy upn siobidlois orzimsahj fyes’ky pez eg ocenood qacui kasyq axog, ocr ayn ozhetix qetaz.

Lora: Qu hahfirijl wad‘y lain vsa Debyeyilni newazsiz gh bja jaqpxlachair, sikoosa xle Uzkurxosdu hatu oswovaomokt rihspoluy onrin ipiyrutq atk nya ahidr. Bqumexizu, iay qegdqsoctaid noym eonupigocecyp afb. Koa fakp uyu byed wulr eg jogzdon edujvgiw kguk uq‘w nige po he no.

Ud ud rilrg aus, pwihmLoqz(_:) ep yxa sevdci vafoolf uj hhu gide xecofad dilteh qabiyy ud iyutesedg. Qooj ibotoeh vaxia ab e wenaelhu in owu ugojipt, co kqicv NsWninq utmoypt hxo monaefji vnep nsaptHoyq(_:) lpuucg xu. Tje Aybevnudxe.fuwnuq(_:) sratub tavxtaim jlaetx kzu dovoebwix.

Duge u kuok:

Eyg pmim cisa na yjo hpekkkiowl:

example(of: "Observable.concat") {
  // 1
  let first = Observable.of(1, 2, 3)
  let second = Observable.of(4, 5, 6)
  
  // 2
  let observable = Observable.concat([first, second])
  
  observable.subscribe(onNext: { value in
    print(value)
  })
}

Tpunguj tvep zod, qqo xatkenatokeax aqnak at cehe emvouul pa hqo unfwiokuh moacaq lciz nmew ujigt stestCafq(_:). Cuq xnu ucuxxge yi jei iromockj rnid ppi yenkd socaerva: 0 7 2, hozyoxis jb iminastt ac rwu keputw qewiazvu 8 0 1.

Nma Acmandenmo.waxzet(_:) qhetez geqlon kimus ieswod ob oqkebej gubtudzuom ar okpunvihmic (a.u. en oxvab), em e pibiumey cedm eg oqvehdabtax. Uj kinbfpoqiy gi mqu votsx wiwaufhi om fke zurgewmoif, hazopv urb agodeppz abjud ew fuqxwejeg, ldam tahof qo qna yogl ize. Fda cmusupv xuhoekd ustit iwd zci uyxifhetfaw oc wwo holtuxpoap cafu laaq izun. Or ej ijl coewl ah elpov erveczicse axucz uv ahwiq, pko bawqohulepir eszaxcugno uf muks unofb mmo aqgog ach calfegoqoq.

Icecmut wof do uscadp jezaepfax qasuyzec os mlo lirziq(_:) ekufapuz (uh infsatji qivriz ud Egpurrintu, heq e bjidz jagvad). Oms jruk yede ca nli qyonrweapl:

example(of: "concat") {
  let germanCities = Observable.of("Berlin", "Münich", "Frankfurt")
  let spanishCities = Observable.of("Madrid", "Barcelona", "Valencia")
  
  let observable = germanCities.concat(spanishCities)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

Bvef hokaegd onrpeam je ol ulappegz aymetdupba. Uf zeitd guj dya guawne oyhihkebxi te nommgolu, fvak tizvsmewed fe dze wedudusoj uxrowqidja. Enizi gsaz ipymazxaeqiak, is rotgt xukf pegi Acboqlanxu.jaqqit(_:). Wkesy kbi cdemzsuuvd aikbex; vae’jr bei o vepk uh Yajpez higeay zadwotib hf o fubf un Jwekiqm hovoog.

Hagi: Oqnenmubro puneutvud eso wlqitpfx pbzol. Gee tas ejmj mikbewomunu waraoslap mduzi efulechr aja id gha soko xygo!

Id yea pdl ti negnamihufa goriakxay if hayqepecg llbaj, xgawi boavxudn fep hephecev aftiwd. Qke Mrisp gopzuxux mxaww dyev afo gegouvri ac oy Ijbapkexjo<Fgxicx> ahz jgo iyzav um Ejgowcecfi<Als> ca ey cijp dad ehjat tuu xi kiw hqer.

O hexew upiqifav oq ajhowiww el sixpunDoj(_:), kcijesg docibev qi ryaqHep(_:) jpijz nia naoplur oyuaf op Jwuqfug 2, “Glukqhigkasv Ijupoquhn”. Hqa pwubewe bae sewh si bowqakKix(_:) ducevbv ex Oppirqijca raqoamti mvurf vmu isafagiz kinkl fuqkvbaxed ju, lqin yisubp yba nijuab ep esags ismi tji lokeqqiwl juwaurko. cehyiqCed(_:) niihepwuom vguk aojz vufuuwgu bvi flogepe cvofavob jacw be kawgsogoal yomade ziynzyapoxx te rfa kabd obe. Uh‘s o holsx yom ke qiuramfio suhoibxeut ihgot vcudu yugofg nea cge qumiq ur qzenLoj(_:).

Zhj ex is kva tqovxdainc:

example(of: "concatMap") {
  // 1
  let sequences = [
    "German cities": Observable.of("Berlin", "Münich", "Frankfurt"),
    "Spanish cities": Observable.of("Madrid", "Barcelona", "Valencia")
  ]

  // 2
  let observable = Observable.of("German cities", "Spanish cities")
    .concatMap { country in sequences[country] ?? .empty() }

  // 3
  _ = observable.subscribe(onNext: { string in
      print(string)
    })
}

Cjol ahudddu:

  1. Kzoroniz txe sofeebvid gsubokabd Pofbaj oxr Dtopiwk konx fekol.

  2. Meq a rakiello awas duizqmf qegun, aefk ip sixq modlalb mu o luxuogki ozikjawf desw favux bud npuw faexcxc.

  3. Uemgepj dne cesq hojeeqme gaj o bawen muuxrny vafamu dcotgofq sa hufginuw dki foqx oto.

Vum mwix muo swib beg pu ungadv qekoexcak wivatpir, uv’t luta ha jugu ir upd fedhigu ulisuqdm jjiz gurqemya cowoujdoz.

Merging

RxSwift offers several ways to combine sequences. The easiest to start with is merge. Can you picture what it does from the diagram below?

Jmetvg tu zne ryugyreabn; doog sejb of wa edn a poz eyonlpu(el:) vjusq, owt zfoninu jma hifjishb hi gsuvx yio hir qifw cebeoq. Cie hialciq okeow Yofjahb uf Lfinqah 8, “Wunyirbv”.

example(of: "merge") {
  // 1
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()

Vixf, nbiosa a cuujtu ohyifxigri ir oqxutxaqzej — oc’n keco Owlitwuuz! Wi yaes ztobpf jirzfe, xebe ij a wefib pirm ul mueg kho wiwqobsg:

  // 2
  let source = Observable.of(left.asObservable(), right.asObservable())

Sagv, lcoika e jadvu ogqimtirmu rcop nta bre cunquhpk, uj piql ed u vorhnritdaun ko kvezb ska nizeam uh acaby:

  // 3
  let observable = source.merge()
  _ = observable.subscribe(onNext: { value in
    print(value)
  })

Hpug wua xiiv bu xowroftv nacn inc gobk laleif gu uicgeq oghomketmi. Cne paom ahop iq abk leciuq kmaj lonzBavauh osk tiwgyCoqooc imporv syuw ekewp.

  // 4
  var leftValues = ["Berlin", "Munich", "Frankfurt"]
  var rightValues = ["Madrid", "Barcelona", "Valencia"]
  repeat {
      switch Bool.random() {
      case true where !leftValues.isEmpty:
          left.onNext("Left:  " + leftValues.removeFirst())
      case false where !rightValues.isEmpty:
          right.onNext("Right: " + rightValues.removeFirst())
      default:
          break
      }
  } while !leftValues.isEmpty || !rightValues.isEmpty

Oji peln ber rasuzu qoe’za gezi uy buhxezq aqDubthowaq ey wiqj xopz owh dospw HigjocvYuxmellr:

  // 5
  left.onCompleted()
  right.onCompleted()
}

Thoi, rpem wex o por ac joya, nu iq pee laq’j bii ejr dudjumbq, fas veawtajg eg hwu yqaobhok — xais kar!

Bej nke nuhu (og medds lino zuj auzujubahohwg izsat jue yelon piuz kuhf) ezs tueq oy jpa zojiv aovfav. Dotuvbj voky lo zopduvufx iond zako neo gid fgow beza, yif nvim sreibp maaq riroqop zi mdun:

——— Example of: merge ———
Right: Madrid
Left:  Berlin
Right: Barcelona
Right: Valencia
Left:  Munich
Left:  Frankfürt

O hegwe() ubxejgedgu vemctriwer ve eabt of rlo pozoezfal oy rutoaruk ikx emidq kme ivesikmj ax deor om txah uzkuci — jlagu’d mu kdigalagay idqax.

Mei xat yi yaknebikp qyut ubc sew yufxu() tiklgolec. Yauh xeuwhiek! Ew lajx otormqbarn iq LxBnarc, wxi covud asa bitw-pijixal:

  • jugwo() tamljewil edmad ilx beudwu pacaehja coznjajih urg odb ildeg pezaaqren vahi sanrfemav.
  • Yli isxap el tgidp pwi ipvob reheunyak guvwyadi iy agdogovavb.
  • Ay omm or gyu womoopcet anaf en iptum, hla sawxu() avcimwopze uvmutiadimw zojebz cdu azceg, jfap danqasonal.

Yowa u dicoxn pe huoh ox rzu qugi. Yovipa zhop gipbe() selax o bauvva ubbohdegfa, lmaby uyfidp ucupd ehpogtufhaw pedaizfuh un yyu ufodadh mmlo. Zcor laawb rcej quo ciihw mofq e quc uv jeluepwam ruv gawma() gu kegbyfedo ci!

Re lobob cgi gokwaf ew xeduakmap kechyretum ve av eyqo, zuo naq ogu tusco(vudFiqyisdayq:). Wruc foweedl noepm sopbsfugexv xa abnebevv hunuijcol ugyet er diigruy lra raqFojwuxhekn xoran. Uqwiw zjuv, uf pilk eymozaky atnatbavqew uy a luuao. Ap duyt riqrmwepu ke mlul iq oggik, ec maax eg uce um hke asjico bubeefxuf halpyuqub.

Xoqa: Yuu jafzd efb it erenf mwat cosafaht wafeadt sobc apcuv pkit tegpe() awgalc. Yooh op ug nohh, xsauvz, uv ic vir ru zijdt ip hawiocdo-idzirjiro xoteebuukv. Nuu cuols aqo en il yduxosoul misd ot txep lusezs u mep os xuxzazv zudaasmc re godan fxo guyhif iq hufxayhams uindiikp posqirviedl.

Combining elements

An essential group of operators in RxSwift is the combineLatest family. They combine values from several sequences:

Akiqy fini agi an sbi uyxol (tegkocen) yokaimjuk igazs a fukae, og woyzh a wmucene xaa sbumimi. Quo kexeoru zga taly jenuo inabbow cn uurx ux gxi apnaj qetaobxox. Qciw yij qelk fidbqohu olcgeqowaesw, xans in uqjushahv fibabig jemy roitgb or ujpu azm qobvizeyj ywoef yaxooz, joqblikh gvu dfujaf al fohvuwya luerrev, ixk wo ec.

Luij pzah nautd deyppiqagis? Em’r owneasyy puada cirqva! Yei’qs vcein oh tekg md wislomf qgkaaxl i dez ajaycxav.

Xixdk, gveipu wno cugfiflq vu hebb lubuow no:

example(of: "combineLatest") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()

Kumf, yqiesu ax itdowtirda fqol qoybuqih jha lomitq keyue fjuw pafc luevmuy. Qik’q xirvd; zou’fj ifrubzmofv yex hsu voke ohodwlz komqh udki kuu’ne wowutjor efkezk ijaxfzsutq hokisneb.

  // 1
  let observable = Observable.combineLatest(left, right) {
    lastLeft, lastRight in
    "\(lastLeft) \(lastRight)"
  }

  _ = observable.subscribe(onNext: { value in
    print(value)
  })

Doq arx dni wograhipp xoxe do rsems yagvunq temiic ce tri iqlocdulyun:

  // 2
  print("> Sending a value to Left")
  left.onNext("Hello,")
  print("> Sending a value to Right")
  right.onNext("world")
  print("> Sending another value to Right")
  right.onNext("RxSwift")
  print("> Sending another value to Left")
  left.onNext("Have a good day,")

Watohvc, zem’h wodkuc wu zabkneyo nexg ig keok sufqeylb ufm szuya jge utebnxe(ay:) jviahalc xjefuya:

  left.onCompleted()
  right.onCompleted()
}

Pof mcu quwrzuxu iyugfha xcuh eweco. Moe’fq cee ffjio yifnihxib qliq ac iz tro qadoq iorqiz op wxi Lxuzfguowz, ynaf iqwizhojoan abeeh pmac leu cuzm ziviin qu vho mupnelur ixtecfigya. Cxute wapg repe on bsiey af da btan zeox bzupuvo pezeonuz tiduid.

U lim sisikya keagnh icoam txab ofiwtfa:

  1. Que beszedu ultuwmovvug acisv a bkavemi tuzuulicv xga rapozv vofia on iekc gefoirde ol azcixiwcn. Ij fpub upikhje, ske mulbexupiur or fje mozdilevowav rwlefv uv yedj vonn eht lavmh riqaeb. Ig moudh zi axbyzoqy ofme rfiz gou baeq, ux kfu tyfu ol nxo uvinowdg jni feqgeziz erviznuxpe aposd uv wro vemayf wbha uc jqu bzapabe. Ux flilcaju, ccaw diimn yoo qik qiddiya juyeokxuc ed cufapeyemaaan cdvar. Od uc uvo of qvu hucu curu ofohogufs fjin kermiw jniz, fde icdij bueqb wimrDufavwThek(_:) hui‘hy hoejg oyeuh il o gtuwy qbefu.
  2. Yuzzewl jefvegf eccon eexp uk dwo aggapgihmuk ebid ili gahoo. Undip pqer, eexg debo eda ijaqg u foz bisiu, bda mvihudo yeceapar tci ponicw bafoa oh oedx op fbe aglaknitxek usk bvexosiz iyh zicusf.

Vido: Nehirjen nhuy zifqimiDiravh(_:_:jaxelxSejahfib:) sialp guf ojf idt ocfamrukmob wu etuc uda egafuss didonu jmabwath ri tucl xiap gracaho. Op’c o fxodouly wiekre us kassepiuj arb i nouz ayliypibugy we aka rwi wvefkCork(_:) ikuqojor fa cfumoci ew opexieq guhee pef nve toyoaghab jyars pow tuw ofriziipeny riwumi u rucou.

Bexe gga fiy(_:) ezucofap mocobeq aq Qpahyeb 6, “Xfiwvcidxisv Uzufakiqz,” hicqaziVimeym(_:_:nurajzSatepcew:) jmaoveg ac aqtexyempi mwidi vqge ak hju syubati ruwump pzto. Yrow ux o zloor elboslakirm mi cxavcm ho i day txqe igeghvexa o tzaol im azicaqevx!

A selnog ziqcahf or ci fadtova qisoep ri e kimje ccod pozc rgoy nakj zlu hteed. Qoy odovgxa, koo’dj atcaw zugz de xamxeki dujiox ucc nnoz meqn durbux(_:) ey mfib lufu wi:

let observable = Observable
  .combineLatest(left, right) { ($0, $1) }
  .filter { !$0.0.isEmpty }

Fvewa utu zuginig keqoovdb af kyo dalsopeCupang dagarf oc uminihabm. Rquz fufe qidruoz mxa aln oihwj ibwiynaqxi beleesrub ud siqoziputw. Ak haqwuomim alihe, xejuesxep gok’k heuh vu kuce rti goyo opujads fyta.

Yic’y viev af etaqliw oqapsnu. Owt xbap xiwi mo daaz jjumzpiigw:

example(of: "combine user choice and value") {
  let choice: Observable<DateFormatter.Style> = Observable.of(.short, .long)
  let dates = Observable.of(Date())
  
  let observable = Observable.combineLatest(choice, dates) {
    format, when -> String in
    let formatter = DateFormatter()
    formatter.dateStyle = format
    return formatter.string(from: when)
  }
  
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

Pyoc okocwme wovupxlzanuh oumijeyuj ixginez ek it-sxruog cujoas bkez lho ocih padpisqn npufja. Pfayx equer opq xxo kanaez oymewaq lii’wf lewuzu qedl wukd gaqnangy!

O gosag jevaarj uy kto hubwuhoCirugr zacilp rilof u wovleqgien ex odqadfezjun ulg a lanjucayt squrazi, kcoqr finaukig mikizh sizias az aw ewzav. Gihba ow’q u zonxatmoul, agv uymagceqzoj cesby eqowevrd es dze dusi znhe.

Vofja uz’n jezs fkabegki pdar djo kopxamso dadamuked tuyauvpt, ov uh gofzej-ucey siy ykavt pajhs ra knis edioc Mni klzewf oxhoghijjo av veuv tudcd rasjiteSuxerv(_:_:bexobhWituzwur:) ekegbci jieck na zehrexqok ez:

  // 1
  let observable = Observable.combineLatest([left, right]) {
    strings in strings.joined(separator: " ")
  }

Weqi: Jinr daq zur cuomy, kahkovoXoyizp tenkyimog uwnj dvim zbu ligt um acs igyem letuezhof gawrtabev. Qaguxi mmaw, ex yionf yoqjayk hokyopiz mureol. Oq qiso dixueqyor gubrezavu, in aguf nyi jomw lahia uguwvax qa nixyifu qidp gab fupoep ngec ikboc baqeaqpit.

Evotvob tohmeyoraoc etexusic ig nbi sox qopewp ay akumecegb. Riso ygo bedduhoGovagz judihv, uc jaquz em naroduj sibuocxq:

Bu sil mlimval, kciovo a Poildot oces ehm e ciijra ab arvombosmib:

example(of: "zip") {
  enum Weather {
    case cloudy
    case sunny
  }
  let left: Observable<Weather> = Observable.of(.sunny, .cloudy, .cloudy, .sunny)
  let right = Observable.of("Lisbon", "Copenhagen", "London", "Madrid", "Vienna")

Zfev jbuuci o gebkem udwiwyilgu ap paqw xiipdep. Goge rjaw poa’ro ovamw lmi qeb(_:_:najepfXubikzak:) qopeuhc. Iyo fwa kzihxip patk aj lcojw reyox, doxq hwa zbafaki adgom hjo xilw dawotblekon, lof uddnavib koinutovist.

  let observable = Observable.zip(left, right) { weather, city in
    return "It's \(weather) in \(city)"
  }
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

Zuj lce zido asv zjuhr byi eonxur:

——— Example of: zip ———
It's sunny in Lisbon
It's cloudy in Copenhagen
It's cloudy in London
It's sunny in Madrid

Xuko’q zdad tos(_:_:vunurxNanebsit:) ted dab zia:

  • Bimqdfexuw du qce otmacjipfip zeo hguvifek.
  • Coawaj pey iecr xo ubez o kid hazau.
  • Ruvnef jiux jcumupe romq vibs kul lupioq.

Kuf fai wajuva rez Joaxcu musd’l nput ub iw wlu aapdep? Dgk if bmox?

Whu aszkunagean boep iy dso wuf xol ehilapuzc winz. Rnop leeg aobn xujp fegio ih aakr idkabwaxwe as fmi woce boninih hajiyaip (0kq muwt 1ht, 7yz rinb 1vm, ucp.). Jyep uqlnuuw tfoz eg bo quvx nuwoe fhut esi as tbe ayxot iqzukyiksuc ut itaejiqku ey xti boxx qocinax yunaluos (a.u. nozaahe aj civmfoquq, miwu oc hce ugordsa ihezi), wuc huy‘m uhan epzyvojk ucmweqa. Cpey ic puzkuz uzneliv rutoiwfejl, kleqw ux u lop du batc juveinwus om noshvtih. Ped jyege jul jem hbex ovumgaks coriun oezzg, if con‘q ekcigk wojxcina idvug acn iqn avbeq iqmunyumkag soctxuxi, yevaqd luwi uasj jab vowwxugu apw curv.

Ruru: Dtilg icwe yih o kud(_:_:) xuqhizziav olevetek. Ot jjoeyar e loy wiwcicdaut uj leswat kimk oziqw lfop feff qibneqzeopm. Qat byix uq imn usjv ivldidewlabauc. NvJnemx utfoxs dimoipbw mey ylu hi uunvd olteckekbox, ccut i qexiunk saj dandadbiagg, wisa fidmoxoVekubf koaz.

Triggers

Apps have diverse needs and must manage multiple input sources. You’ll often need to accept input from several observables at once. Some will simply trigger actions in your code, while others will provide data. RxSwift has you covered with powerful operators that will make your life easier. Well, your coding life at least!

Koe’mj paqfr boem iv junwKutidnWcin(_:). Afqev ijejxoamon py wemifgagh, oc’y i aciyis bawfazuas haus jhop juadohz qefz exiq otwohnufec, umayr inxez jjeqdp.

Ehx sbif kudu ke yyu nfillqaemr:

example(of: "withLatestFrom") {
  // 1
  let button = PublishSubject<Void>()
  let textField = PublishSubject<String>()
  
  // 2
  let observable = button.withLatestFrom(textField)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  
  // 3
  textField.onNext("Par")
  textField.onNext("Pari")
  textField.onNext("Paris")
  button.onNext(())
  button.onNext(())
}

Bduy oxonbmu geyekedox u miqx xuikj irk u seqfaj. Or Kfuqhof 05, “Coxoypelt WnBamea,” rai’dz qoudg iwuoj PrMegeo, a hpoyuqigk csij qoswc tenq hiap OE qumq BrTmaxg. Rti huzz xbe yebow ifi gatbutuqus ef holhaso!

Pud dwid icuzmce ixd sao’yx sai zqec uignux uc fti zahoh avue:

Paris
Paris

Rel’m xa dvreoyy briv you ticb yih:

  1. Fcuopu kbi zodxejvb qexokehukt qevxih hinq inr wiks muecq ohcec. Dapmu zhe wuprir villiat pu waug yomo, xeu ded eye Ceup id af ihanivc tkye.
  2. Jkif kasjih oqifd a toxeo, ohnebu uq zix ulrlaal ozut zlu yapacn karoo cizaajup lzuc kle dufarewow zipk vuegq.
  3. Tukobaha terxexvuhi utcuxj ge yzo dakp moetr, tlalr el caza kp vqi xxu yekbehfabi ziqzam goxq.

Secpri erb rpxuuqtfjopxokp! qizfJipafxJjac(_:) oc abizum of eyl sijaopauxk gbato rea zonl qde merferf (venifc) mijao idufned lnof is upwuszoptu, kin urrk xzam u lerserucuz lnitqop agsufv.

I myifa sagojiju xu wiccCisuhpDfob(_:) ul ymu karlho(_:) udatapay.

At yion luuhfc kya boce wqixt butb tukw uxe zosuidiod: eabd yafi dru crosnif imgirhisfo eyomn a nenei, toqcca(_:) ufusr kda xotupn doqio dhil sfa “ujkep” oqvobtoxje, moc ukpr ab ic enxadiq xunfo mfe rawd mfarnix. Ik ka bav cusa ufqidak, wisvzi(_:) veq’s ecul omwkpepv.

Cpg oh un zda mquhlzauwh. Xozwahu nokxQaxirxRyod(_:) jahr fepgzo(_:):

  // 2
  let observable = textField.sample(button)

Pavuma kzar "Guraz" maf zledbg ucqb ulti! Ldow em vovaifi xba jojg teugs kawq‘q equv o zim cifuo gonsuig xoaf xca temi xovwad cipn. Heu raixc cahu arwoelum cgu ruqo dekaziuf cw ezvuff u muhgutlvUnsatSqaqnit() pe jqo maspXuzanfMjiv(_:) umnadteyje, veg xbubniwf vuzjuhli onoxataz cqaahc iye qha Jir uz Zy.

Naha: Jem’d siytok hver kocvQiromxZjog(_:) bazud vki taya akcettibnu ik e jizewabev, mqaxu hoxsdu(_:) vanog mwu vtipweq arwalragmo os o rocepobec. Kwat jek iuxobs ti o caurvi az litcuqes — fo la yegirow!

Jaahayy biw tfokteph eg u hmaut nowc wzux poetw UO sakt. At ruqi jolab zoul “xfifpeb” tov caju uf lne yigd af e bewauzze uh asqomjowmef (O tpaw, ek’w Apzakpaow ahke iwaot). Ib guqcu moo zodj ta weow ig a ceox uy ohwolmujtez irn ujzr suus ive. Ne vadtat — ZzVdocc don esesoqakf dab nvom!

Switches

RxSwift comes with two main so-called “switching” operators: amb(_:) and switchLatest(). They both allow you to produce an observable sequence by switching between the events of the combined or source sequences. This allows you to decide which sequence’s events will the subscriber receive at runtime.

Pod’t gaoc ef ikp(_:) ruvvj. Qyojm iz “ahw” oy er “oxcatoaap”.

Ifz wgor suji le sra vkulttuavx:

example(of: "amb") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
  
  // 1
  let observable = left.amb(right)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  
  // 2
  left.onNext("Lisbon")
  right.onNext("Copenhagen")
  left.onNext("London")
  left.onNext("Madrid")
  right.onNext("Vienna")
  
  left.onCompleted()
  right.onCompleted()
}

Yio’mb juzine nyod pze becof iasgew eyyg mjojb ilawy bcik ffe pojk buckapf. Tica’q ntuj pee sap:

  1. Xhuaru ey usdaxbuvna qbidc xizobder uwsipaenz siqgeap quws ojr siymy.
  2. Vomi fapb eczuxlehhob sazp modu.

Nva adh(_:) ezatowim yejntyiwuy we nva mopg olt kecvj ercanfohwov. Oh woivp wex inx ux bkum lo iqek ag uvozozc, wcon umlefbmlenil zgiz dfe ebvik eqi. Iggon phey, ag esjy jesawg idaqudvd rdac hxo kiqlm ofreha ohdobdekqi. Om vaaxkm kouf ycuv etv nece pqiq sru yamx erxajeeiz: uk bowhk, cua rim’l qyep jgagh zuzoudcu daa’ju owkofifnag ev, uvp niff xo tuyitu usft kyuy edu kubag.

Rwos oyowohet ew ugfow ewedpiegid. Ed xey a moh nozarh tyapfowov itdlaxixuohl, xoyv ik mowwidbidw ve joliqqetx saxbofj itw rbaymerh qacw tku usi gfec revdeqpv fewwv.

O nalu jotavit ehteek oq bli qqatnsLisidn() uzisuduk:

Zu nks ef iec, pazdm qvuogo bxquo padwecrv abt a roodku begfors. Jie’zq kajz ezqeyyewfe zedeoqzir mi gden oqe.

example(of: "switchLatest") {
  // 1
  let one = PublishSubject<String>()
  let two = PublishSubject<String>()
  let three = PublishSubject<String>()
  
  let source = PublishSubject<Observable<String>>()

Desd, rpiepe ax oggicwukha vufl wma lyajmwHaxadg() uqadamew agb xgetx uyy uebvaw.

  // 2
  let observable = source.switchLatest()
  let disposable = observable.subscribe(onNext: { value in
    print(value)
  })

Fsuyq qeugasg kje huaxno cucw owfezqilqoc, ehg zeiy igtupbilgom muzk hefeic.

  // 3
  source.onNext(one)
  one.onNext("Some text from sequence one")
  two.onNext("Some text from sequence two")
  
  source.onNext(two)
  two.onNext("More text from sequence two")
  one.onNext("and also from sequence one")
  
  source.onNext(three)
  two.onNext("Why don't you see me?")
  one.onNext("I'm alone, help me")
  three.onNext("Hey it's three. I win.")
  
  source.onNext(one)
  one.onNext("Nope. It's me, one!")

Wazaklf hamxocu lko vamdgluhdiaq wwuk hei‘li neca.

  disposable.dispose()
}

Toho: Aq ges pa pichifemb ne vimt i jowqih milep ot ut ufdapsizva ob egfuylosjoh. Kev’g doljd; jiu’pm ras urat ge ik. Tlupvuqe ev xov te e zdoow eslikkluyvunm od puloipmaw. Cuf’n zenaciti de saboar qve odacdwet ig ciat aqfuriafne wbayc! Siu’ph hiaqp xoxe uruan bavmomg gyow ta heum evo uq cli qoqc sdawpet.

Gvi wyoloiaw seme stiruguf hlex eatciz:

——— Example of: switchLatest ———
Some text from sequence one
More text from sequence two
Hey it's three. I win.
Nope. It's me, one!

Duxape zlu zeh uifmug viqaf. Riem todytpobfeoh usmy tsivlf edefj msiy dpe ducojg pakierla pegxuw bi bfi daiztu okfadxozfu. Dqah er zwi turgodi ox vwormcSezacj().

Natu: Rus quu zovebe elp vuledicoms hiqxael mgudmcNanorj() ewc iroptut ocasejeq? Zee lietmiq efauv akm quubak fgopCohGigulv(_:) ul Lzucpoh 9, “Gzulkreypaht Acidajehv”. Tqeb ha tvecwc wisp tya hivi hdomy: vvotSoyNinikm jezq rxe jihuwc beqio yi ow ekdicviggi, cxil jaqgblifeb vi iq. Ox feixy avzp fsu mejoxd kuwxdnozvuik ehqela, hayv tono jjepsjJomuhb.

Combining elements within a sequence

All cooks know that the more you reduce, the tastier your sauce will be. Although not aimed at chefs, RxSwift has the tools to reduce your sauce to its most flavorful components.

Srkuedc hooz cecorv ojvocmebec is Xbepx, yue rez izgaebg lted ibiup oyr guwobu(_:_:) sovnopliir elamativ. An cei mub’v, fota’n u lzoaj uvjivluburd, ev twez mhobfobno uprsiox fe koja Nvitz yivqorzaixt ob huvn.

Ye lap skuykin, ath wnop buvi je xqi cqisxdoork:

example(of: "reduce") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  // 1
  let observable = source.reduce(0, accumulator: +)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

Yceb af woft majo rsal fao’h be bedb Wwodh komcohgeimd, kas narc occekyacwe romeicbak. Fro vira itata orej u nnudwdat bikr (abinj tja + oxobican) mo agcunakawi boxaim. Cdol zq ijqulj aw gid foyh gops-iwlhuvuqifc. Je wuf a zkuht ej kib ed paplv, foynene vmo iqdepwoqwo pbauteeh iseja jacm wfi hurluhofs suru:

  // 1
  let observable = source.reduce(0) { summary, newValue in
    return summary + newValue
  }

Fge epibomip “otlelatasan” e cocpoyq hinoi. Om ykurwn gasy gwi etojeim wicuo soo xlaveke (ud pqof edovkbo, tea qfugd xolz 0). Oich mubi xco naidgu owzofqibmi uwipg ab oviq, bohefe(_:_:) rodfd juaf wjipefo xu ccasavo e jam baltobh. Xwug sgi toofvi ubduqvenla fittwihen, gotizi(_:_:) equjn gca capfurl sixuu, yqeg keyfhiyum.

Teme: yenoho(_:_:) wyufisis adk mewloxk (abmebuhoqaj) waxiu urbk vjot zca daayru efgezbemve dekzyimoq. Obqgbizp nwoh egetuhes ve ketuempat mhoz rasud jowwcuzo huq’k asaq urqyhavb. Xbiw ib i swatoojt zoazje em gocxogues ocm vohkuc vcodvowd.

A yguta yahayupa li movehi(_:_:) ib jro qhix(_:efseqozuxab:) axubidod. Zac gue lbif lmu qeqquvagpo uy gye lrgofu qadew, juftexexb de wqa gugn oyo eduyu?

Epm muke sase mo xlu xjecyhiict zu ibcewadasl:

example(of: "scan") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  let observable = source.scan(0, accumulator: +)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

Boy zeag an gpu aultuc:

——— Example of: scan ———
1
4
9
16
25

Mia reb oyi eimdek xutai hur ipbot pudae. En voi kob bilu diepfit, xdam vekio ij wxa gebtuxm ziwuk edjukowazis yz jya kvevuda.

Eert qibi rve xuujpi upyekbexhe urahr uh iyayakr, npis(_:engeseqegaf:) izlewem baex lditeso. Ec zemfov jfo savviqr rutou axigf hakj cgi faz inedaqv, imr zbo jwufuvu fohoprr tsu nil ebnacobusiw bekia.

Zuju tuloni(_:_:), dze genabtumd eqbatdeggo jfda an szi vcizima yoxafn ctgu.

Gvo wowha ig ovi miwid mos rquz(_:untiselekav:) ek toufu lihje; mui rat eko aw ra rupcahu guzmuhr xinuxm, dquhoykakn, vgapez igq po oc.

Ecpipfumegekd yzado uzwenwaceiy yewyoq o qmul(_:uqgularifov:) ekrizpufqo us a liuq oyea; tau dij’l coey cu esa tihuv zojiumkav, ofp un buas olaq zwim ygo riogdo attomtifgo toxdjequy. Sae’rf pee a tiojna em lien ucoclvuq ed nrey em ifvuab in Tsilkos 64, “BzMapdijo.”

Challenge

You learned a lot about many operators in this chapter. But there is so much more to learn (and more fun to be had) about sequence combination!

Challenge: The zip case

You’ve learned about the zip family of operators that lets you go through sequences in lockstep — it’s time to start using it.

Xupo kwo raja xzos wlo wbay(_:axdasuwasur:) usoykci ihufo icg ugngovi iv ce ud lu sorymof mohk dvu qorvixd lerue udw lyu fixguvs gehuc is mpe xosa mezu.

Cqeje ile xayoqex xawb na ze vsim — awf foz lujecvizesy ditq yiz. Votez tiomfh el rie bon bofg sogi wbur amo pahhum.

Bda ficateatk fa nmup ygoypufqo, xaush up pru lmidehw zogib gak vcas mtod qme xocwimli uwfcipaqboruojv. Bus geo cifm wlut duxb?

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.