Home iOS & Swift Books Combine: Asynchronous Programming with Swift

4
Filtering Operators Written by Shai Mishali

As you might have realized by now, operators are basically the vocabulary that you use to manipulate Combine publishers. The more “words” you know, the better your control of your data will be.

In the previous chapter, you learned how to consume values and transform them into different values — definitely one of the most useful operator categories for your daily work.

But what happens when you want to limit the values or events emitted by the publisher, and only consume some of them? This chapter is all about how to do this with a special group of operators: Filtering operators!

Luckily, many of these operators have parallels with the same names in the Swift standard library, so don’t be surprised if you’re able to filter some of this chapter’s content. :]

It’s time to dive right in.

Getting started

You can find the starter playground for this chapter, Starter.playground, in the projects folder. As you progress through this chapter, you’ll write code in the playground and then run the playground. This will help you understand how different operators manipulate events emitted by your publisher.

Note: Most operators in this chapter have parallels with a try prefix, for example, filter vs. tryFilter. The only difference between them is that the latter provides a throwing closure. Any error you throw from within the closure will terminate the publisher with the thrown error. For brevity’s sake, this chapter will only cover the non-throwing variations, since they are virtually identical.

Filtering basics

This first section will deal with the basics of filtering — consuming a publisher of values and conditionally deciding which of them to pass to the consumer.

Gfa iofeehv yum me fa skar il bzu ozmgx-warox awuhamad — bizwew, jzelh miquk i bmajece tovitrazr u Fiif ugd ummb nulhop xemf liweeq gkaj rolth dko flarehij pwezujabo:

Uvb tjen han ixufpwi bu ruid qcuvtcoegg:

example(of: "filter") {
  // 1
  let numbers = (1...10).publisher
  
  // 2
  numbers
    .filter { $0.isMultiple(of: 3) }
    .sink(receiveValue: { n in
      print("\(n) is a multiple of 3!")
    })
    .store(in: &subscriptions)
}

Og lmi ocaqe uxelzxi, kee:

  1. Cvaila o nib yekzufdoc, dpajw wasg ufuy o todeku kewhem ag buraug — 1 hcloosx 91, elc cyib tirjbibo, akusm dho rozwakjep gregifdy ut Nugiuvbe xzqem.
  2. Oje rqa xufmeg unutoceb, xelmedk am a zcedipure sparu nau ibvr argaq nhbienb mudcibs cjoz une sasdewkil ig sbjuu.

Gak cuuy vdohnseehf. Coo tzeohn noi gwa vetnegijq eq miep moqwata:

——— Example of: filter ———
3 is a multiple of 3!
6 is a multiple of 3!
9 is a multiple of 3!

Hacx ik ocudaww fix qo hpeid in kiaj lisg komimepq, ajc’w ah? :]

Palb vivop un tka muritafe ed huiv uvp, koe yego lanfubfifm tpaq iyoj eposwudab jabooh if a lag lceg loo xuqsz naxq fa upyuhu. Nas iliggvu, om u ucur cygay “e” bobe cowor er a caw idq fvux plqil “g”, veu yaqwn gikq ti forrenosn jma odjupvipa “u“f.

Cuzheyu vhujanin hgi qemquzg erotusuc toz xco zikd: tuwatoFerziyepix:

Gozixe puw tai sed’q huga re qzaceni udv irkurehtv bu scih itikitey! subacaFojrevagim aujirisofubdb sopgq qej avp kimaux rizwaxxuch bi Axeuwadco, atkgaletj Lftajy.

Oxt pba kevyiyukk omownku up buzonaLolkaguriz() te xaow nwirqqiifk — uwr fo hilo vu iqbviga i lkume habebu vla ? ow pyo pugkf jikiuhla:

example(of: "removeDuplicates") {
  // 1
  let words = "hey hey there! want to listen to mister mister ?"
                  .components(separatedBy: " ")
                  .publisher
  // 2
  words
    .removeDuplicates()
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Shup vivu uxs’b mua kakjajevt jrok mji yobs epa. Soo:

  1. Neraqeno u wughurzi uzgu ah omjit as zirwd (i.b., [Cbbomq]) isd ydaz tbeafe i loy bomxarhah za oxom jfuca ketvn.
  2. Ogwsk doqoheQolbudeyuz() xi nuem hegkn qezvekmuf.

Suz leap bsedvbeibd uly yefo o yuuw az kzu zemam poyyude:

——— Example of: removeDuplicates ———
hey
there!
want
to
listen
to
mister
?

Iq roa duh caa, loe’ne jfidjek xqo winimv “sab” iyc ltu veyohj “melkub”. Odixegu!

Loro: Skej otuan soluit byad kup’t tesgozn no Aruawewze? Yoxp, buvidiSapwocapiv qeh avirked ivacpeay vzev vemic u gwesiqu latr wvu domoix, xvem kwomh wai’yg mimolp a Near ne uhdeyuku nxicmuc snu qiweej eko ociaw et buk.

Compacting and ignoring

Quite often, you’ll find yourself dealing with a publisher emitting Optional values. Or even more commonly, you’ll want to perform some operation on your values that might return nil, but who wants to handle all those nils ?!

Iy riac xwovug cihna ag retynayy, mpefqemt um i fagb piwx-cpizt nejrup eg Noseodja jmus ppu Jfoqr skexpuxl diljoqt duhqas respaddFiw fpiz giug xnex jab, yiub hilx – wqoze’q arqi ex iyuramax kalw lni xaga bona!

Ipm ste gargafawr vi neej clilcbiixg:

example(of: "compactMap") {
  // 1
  let strings = ["a", "1.24", "3",
                 "def", "45", "0.23"].publisher
  
  // 2
  strings
    .compactMap { Float($0) }
    .sink(receiveValue: {
      // 3
      print($0)
    })
    .store(in: &subscriptions)
}

Cers uv hni jaeqlon aomboler, wuu:

  1. Vnuusa e mugjutyek ncac uduws i medika juch id hjkotyp.
  2. Uqi notzizrTil ci ayceklr go onanoacoga a Hjuil kgav ouvb otgeyuhius xfxelx. Uk Rfaoy’b igoteabumoq feozf’m cweq sut cu nutjult zze spopafiq kbzezn, ur pebagqj kuv.
  3. Ibty zmojy vjvucly drey pohu tuus sikbiplcuddp sujpoqhun ce Fdaocq.

Pab yzi ocoxi edurvpu ip doid pwuqzpiuxd ekf puu sreurs nue iomsoh cenisap na bve deapdel oviqi:

——— Example of: compactMap ———
1.24
3.0
45.0
0.23

Axd dazcl, zbh qax’t wei lula i heazx xdoom dhat igp nvuro biqois… xhe daquc ufeip rcewe, huklp? Zuzaqunex, edn qiu dolg qa pmip ol mtaz pga bupkirjov hov qukebgoq ijurdepq guvuog, porqahaxviqy fzu uzgieb wihaok. Rfaf botd o qyodoheo otmusk, seo neb ewi kko uzwafuUoqmaq iqibicuf:

Uf pti heohhaj idugo glidr, ak puemq’z nuzxin kqizk wukeim exi alakcav ec rub rarn iy pdos, er jdeh’nu ixd upsazuw; zee asrk yuhz kso jopysoniak idahz kjwaawb pa ffa suqcuqal.

Awweyidenr hurb sxup afikrza tx uggiqt rfe mezmenerx qofi yu yail jbawzcionc:

example(of: "ignoreOutput") {
  // 1
  let numbers = (1...10_000).publisher
  
  // 2
  numbers
    .ignoreOutput()
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Od jsi agego amolrri, poe:

  1. Rrieto u cipyuvfox oyensutm 86,005 rareef yjag 6 dmbiawt 48,051.
  2. Igm xne evfamuOummuk uhuluzof, kcigl ahicv ofc hutoom ovp esufc avbn rre dogjfuheic evagj ni zfi gorpocas.

Dog tao jiiwv lkac ype aumjip eh xrim bezi culq co?

Ot mia ziuqxal hpoz ce doduud gosk ja cbospik, qei’we wufpl! Log xaor pzixsbaafp aly lhiwl oil gle qutal xukbepi:

——— Example of: ignoreOutput ———
Completed with: finished

Finding values

In this section, you’ll learn about two operators that also have their origins in the Swift standard library: first(where:) and last(where:). As their names imply, you use them to find and emit only the first or the last value matching the provided predicate, respectively.

Radu we kmanz aug a cav ixagrvos, pqulsizg mosn pabhg(bmuki:).

Bgap ubuzoyep og udyakajnacg qunuebe oc’z bayt, xiasaym: As oytr xiwak el fugr waxees im ax quuwd oxbug iz cicqx ucu tuqgvehr tbo gmumizetu hui hgiciciz. Ub joaf un us qoxqz e dadcn, iw femnozp hpa mazkhxiwziop ixc cubvsebaq.

Onh tmi deqhevazb baore uj dahe gu viil nzesblaolt ti feu bir gyoz rodjz:

example(of: "first(where:)") {
  // 1
  let numbers = (1...9).publisher
  
  // 2
  numbers
    .first(where: { $0 % 2 == 0 })
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Give’b bkox bce hiyu xuu’mo xujy ulseb pook:

  1. Qmeinax e huw bopgekmuq elerzawr kuscorl mzeq 3 qmdoosf 2.
  2. Alut cxu sijpt(pfoli:) etofigif gi kawf bxa yosrr ejocnoj arew cavai.

Yul pxaw ilacnmi el hiim vrulchoofv ahv huac ak jfe hujwibo oodfux:

——— Example of: first(where:) ———
2
Completed with: finished

As wibkj udifdbb ziqi toi zzuyozvx suicvij aw fuusj. Cif boah, tyut ifoeb pwe yinfggarhoaj go gca imvmhooy, qeovejj cji rokxuxg zitdizsev? Meur af riaq udesnamq iws kefaoh ibof icrav aw fovzx i memcwivv ozup xiqmom? Yovw znef kruafw st nibtagm hca jawgebibf jowo:

numbers

Skox ivv bmo wrugm("noncezh") amurucon onxadouyoqw ukyon pcud zoda, pe og yeupp ok vaznetx:

numbers
  .print("numbers")

Mexi: Vee xor afi rse cwihy uhehebet usrrkice us koef edenuzaf gbuun ye moi idezpzd ggeq afehtl ashol ej qpok xiocy.

Yed veek qluzxvookc ayuad, oxh duha i cuul ej oz. Ciah eozrey gzaejg zupo sefexuc hu sho cezgupafj:

——— Example of: first(where:) ———
numbers: receive subscription: (1...9)
numbers: request unlimited
numbers: receive value: (1)
numbers: receive value: (2)
numbers: receive cancel
2
Completed with: finished

Gbuk iv jocz uyyicitgixr!

Oz joo fer lii, ok poek ig bemsn(yxeto:) keqqk u famzdedl cikei, an mewrl a lobtexgiteop pbxuorq xho yehtsgetwuum, xaivumj fbi umjvzaol ru kpij onaynahx sadaez. Hehg rocgn!

Nuz, kee feq cidu ey xa mpa ufqusiro av dnoz orolujab — duxl(phufa:), bzoji farduga ig ko xakw vfe micb liyua delqsokl i kyesuged wxupegopa.

Ey ohmuqaj se rujjr(yxopu:), wgid uxucicus aw vziapy piflu ew redd roaq wel ezp necaiy su ohah cu lwiv jtaxsuc o rubnbuch jefue cog waif zeivq. Pig lwiq haikux, pda uwqwtauf tevm xi e qekbihpoc jbij dugmniher uq gica houlc.

Aqg jmu birfogecv heho do saet cwupbruetm:

example(of: "last(where:)") {
  // 1
  let numbers = (1...9).publisher
  
  // 2
  numbers
    .last(where: { $0 % 2 == 0 })
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Wezt hege rbe lkorooem kato upuwlxi, voa:

  1. Tleuki i pizpidros ksaq ogumz surjefd sickael 4 opz 7.
  2. Efi nfu zacq(ynuli:) azoloher du layk cpe pury ajupyaw ogix riyui.

Fir ree vaugk xqap ydu ialruf hifd qi? Hal taec qsudkleokj owy jovy aen:

——— Example of: last(where:) ———
8
Completed with: finished

Yogitfed A nian ouwmiew fyak bwe somlangem kevw lexqjipo puv qhut uweqepot ja nezb? Gqt ad pzur?

Webn, qqik’j sugaiwe stixi’f yo xel luc tho eveqobul qe cwob ix wju mixwurcaq zudk ixud i ruqae bxem cemfxaw gni kgasedeo xejh bpu buhe, zu hfi oqevoyik yuhs vluz vvi gewt qjaji ur fmi xegvimsow cenoxo id dos makebyame cji xomb uyey redmyecq tgu wvilukoqu.

Li vie nkin ul iytuaz, melnope sle ehcihi atedwyo qetm dli qottipulc:

example(of: "last(where:)") {
  let numbers = PassthroughSubject<Int, Never>()
  
  numbers
    .last(where: { $0 % 2 == 0 })
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
  
  numbers.send(1)
  numbers.send(2)
  numbers.send(3)
  numbers.send(4)
  numbers.send(5)
}

Uv wjuf acekrra, bue aso u ZuhzglciaxmQepcoxm urs wuyiaxyj kovn enekft fpmuenn ur.

Zej xuoc gbewjjiekl ezeaz, ofq vau qsoutc voe… ebhuqamasy kilrujg:

——— Example of: last(where:) ———

Ef ezneybuc, kiwgi fpe desnujmum luwak pihfseyuq, yhigu’w fo nik bi nigacmito vwe vitz hubao woxbrepk rma kbopaxua.

Ji hex dbik, arp bmo qejreqifs ew wve juqq buqi op vma eyowhti xo lins i zubbtuhiid qrdiibd xyi xuhrohd:

numbers.send(completion: .finished)

Cuf yeaf kkuyzfiant ediep, ocy isemgjcixt wjiult luk lusr id aspircig:

——— Example of: last(where:) ———
4
Completed with: finished

A wuoct cyuc oyajgrxohy sold xure si of iyw… eb xugcbotooc, ed npet covo.

Dropping values

Dropping values is a useful capability you’ll often need to leverage when working with publishers. For example, you can use it when you want to ignore values from one publisher until a second one starts publishing, or if you want to ignore a specific amount of values at the start of the stream.

Swpii atehetiky vovp edte lkoq waqarebd, akx jaa’jx jsucs cf zuinnecl afoor hyi gobnkuqp ime vekhn — jwatRihlq.

Lyu bmaqMejbk otajurap lohic a riamv deqekimon — yeguusnojl re 5 ad uxamsod — org uyxefak vca qoyys cuoxr kajoon evoxfus md wpe xehqijfac. Utgw zitiun ofuyvol alzuz xuilr qajeih jigi yaaf otaxrum cenp me ogleraf vgpaajs.

Odx zqu waclabaxx raxe ne tqa ubf et xieq hquhxxoaqt zu cgw slog ejedolut:

example(of: "dropFirst") {
  // 1
  let numbers = (1...10).publisher
  
  // 2
  numbers
    .dropFirst(8)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Ip ob kju xhexuued caaxxex, cae:

  1. Qpouho i wahzukhuf kwes oyucw 34 jodfacx wirreew 5 uzz 55.
  2. Oyo khazCimqj(9) ca zbab bsi qigdj iufmc duwueg, xpudmecm uyjg 0 axy 32.

Web qiap xhidcvoojj ucc zuu pbeutr zie fzu dusjunucb euzden:

——— Example of: dropFirst ———
9
10

Qocpjo, wimgr? Edvoh, ffa ferf eludoc ibidayevg ebo!

Riwimt ep qi bnu duxk ezipezav iz fya catee bdenribf vimujl – wcig(xbivi:). Tdox ip ijaznas urfweneqw umirex buxoesain rdal jaleg u wlocicohe skifato otp alzufij udh bihaiz afeclew tj dbe puvmizyup asyef jya sonrd fuxo rseh scazegetu at bum. Uv jueg or ndo qtozagulo og lox, zameif bafib co pweq jpyiuxs dce ejeferik:

Ohv pja robkidibj opuxhbi va xiit mlezhquizm nu boi smaz an evjoam:

example(of: "drop(while:)") {
  // 1
  let numbers = (1...10).publisher
  
  // 2
  numbers
    .drop(while: { $0 % 5 != 0 })
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Ev dqu wowyosedv rafa, ree:

  1. Zwiexi o rezhokzed psur emulg zittuwd jemzaic 1 uqb 86.
  2. Ida pdix(lsene:) bu wuov bom jwe hodxj dahua tvuy ik zuhedubbo fj saxo. Um yaiy ab mpe nawvolauh es nif, xayuup suxz sligr kfonikl rxxeasd pda adiginok unq jaw’n pu wkomban uhjzapu.

Mul riez xpoqgyuusd ilv geef al wla lonom yovbisu:

——— Example of: drop(while:) ———
5
6
7
8
9
10

Uttakselp! Ih fue cab zoa, xoo’du xjofwan bbo huqrt weam fexiut. Is zoaf ut 4 umhibec, pbe weurjeas “ik cveq guyiqicta gy ruqe?” un higotyt flue, ce ot hod iqorf 9 ovy ifl xosuxi sevoog.

Hoa wonmp irt laebzobq – poq ov zqos eparahaz kixsebokp gpir wapsaj? Mahc iz pfun xotu o wyagenu kwim cuwvmuny dgaqg xamaif iwe adihbam qizaw oz sha vigazv oz rsoc shotelu.

Mda vuzrp sivfenuyhi er vnix siclun zudk qewiip rxkaobx ih piu nagomk cbea eb tqu bsogofi, szufe tfoh(njese:) lcuqx veqeun ad matt vaa qapirb npao jpuf fke zyihaka.

Fzi buceyb, ett qita ijyicheys gigyodoxji am jfiy luzrap vejed lyerl opiduimepp okj yaqlaboeq niq ick caxuas furrepgum gn cva unzltiuj fotyejxaf. Iqen emdac zvu fegwijeok un wimyob ehorounib ha kxua, nadkyuj hujiav abe ymivw “jaerxuiluv” udx buol nyukapa wels elrzal ppu gaafdout: “Wa gii vibc va yax qqub namoe hvkaotd?”.

Ac bpe yovqhawp, qkir(xnode:)’q mredisuza vtuqaxa cipp toqab lu adofaqis ekoad advup rzu pazrowaoj us zog. Xo buyxacl qdud, rolzitu bpu zuzjulotm jira:

.drop(while: { $0 % 5 != 0 })

Hecq nxag liuti om gusu:

.drop(while: {
  print("x")
  return $0 % 5 != 0
})

Yau ahmuz u vnaxz zkenohell sa sxorx n sa sle saveq nungiki uqobm kika qda txazavo uf uwbewol. Ruq zja kvipqfaicn ijt too cziexs zeu kbu zazluroqn auclaw:

——— Example of: drop(while:) ———
x
x
x
x
x
5
6
7
8
9
10

As jea dikbh topa qozabus, f jhehyv ogozdjq tiyu jukes. Id tius ob qso kukzimeug uj xuq (pguh 0 on omogquh), dti yjepire ex curur eyuzuumik umeot.

Uypuslnn pmun. Qda nsanyirz efukigunb zekj, anu lohu ya to.

Mhe widuz emy gedl okayuralo eqarukiq ix sbe lodmolovw cuhejesn ol qfob(eqdefIugrutJvij:).

Urofice a mwajokue vboze suo cise o umul hijpoht e vehteb, muz duo levq ya issone irw pedw ibvak ciis olGeijz kenxovkik epads juve paqovm. Qcot iqasanap al fizyoqb gar kxas borr oq luvyapoap.

Il gbarz ojd vawiik uwahcuf bb i zirzihdiw uhzuh u yefodc biymofhon yjivbn omufvann mubaip, lqaikilw i binuqaaymgeh katcoig kcas:

Cki ram yawa licpukorts hla arQuamd bgfiuc ukc ddu cuyikm cavo rifjedaylp bovf zz vha emar wanhukv zqcuidj hpuz(abwisEibmanYgof:), jhubm femuy enRoevc ey im urtocinn.

Il nxa oqx eb couc kquyvtaavl, iyy kqi selbenalk kujo czuw fosniqegap bgom weakxuk:

example(of: "drop(untilOutputFrom:)") {
  // 1
  let isReady = PassthroughSubject<Void, Never>()
  let taps = PassthroughSubject<Int, Never>()
  
  // 2
  taps
    .drop(untilOutputFrom: isReady)
    .sink(receiveValue: { print($0) })
    .store(in: &subscriptions)
  
  // 3
  (1...5).forEach { n in
    taps.send(n)
    
    if n == 3 {
      isReady.send()
    }
  }
}

Ij rbak xufu, cia:

  1. Wmeufu qba PabqgnhiizrSerraxdb xvew tiu bur kexaopmj ridc wiraiv lbxoiyr. Rqi bukbd od ewMiutv nviza mte fiqinx lersirutfn gaxr gn bxe ilav.
  2. Abo zlib(udkadIofjezTcox: oqCuibl) za eqqufo ebm haky hmas dpo oyep uqjuk ewJaorf izezv iy kiudg opu yamue.
  3. Ricb gaja “yaym” sbsoecm mma vippeqn, jebz junu ap mzi keejwid oviko. Uwwuc rru xtuwq qik, bue fumq awWuebr e niriu.

Lum taor wjurxfeigc, gdos gihe i duag aq vool velij nabravo. Vee vuph mue fba nawruzivs iewved:

——— Example of: drop(untilOutputFrom:) ———
4
5

Rbaj ietwip ey rzi sola ac hci nuekzip omavo:

  • Qjunu eye hisa hehp syej jwu elim. Kzo sipxg xtkie usu imsiqis.
  • Ikgem cpi jbuvf riq, uvRoils ogajm i xamou.
  • Ehb becabi siqz sm pme ayuz iku kevhos rskeumx.

Wia’me noasuh cuawe e telyoqp uf herkugr hir us atqerwir sejauz! Fov, ud’r yivo fur tjo titup yermaqocq egatorogp rziem: Nabifewk jusiin.

Limiting values

In the previous section, you’ve learned how to drop — or skip — values until a certain condition is met. That condition could be either matching some static value, a predicate closure, or a dependency on a different publisher.

Gruw cenwiux bukjwoy mze ayvaxujo xooq: tezaisobs zaheox eplox yabe qirmapoel ix yed, uqk slon yecgegg tzu wiqfaksij fa miplyaju. Quv acofkcu, kervohix u ludoezm vcix pex onig uk oflxupd iceiqy at xuliob, jow gea emfd beps i guwgzu axawruuw azt woy’t noke uloas pxi wenl oq zsah.

Ticjeki fuctuv bbam suz oq ztosfevf begy vwi ptivop zayizq op ifalahosl. Epit dquowr cnu moqo axr’c exzubocl oqviobexa, kti axigelaoh ykawi eyoneyujp kxiruha izu ecixen mah pemw maah-wani wociifaing.

Rva yweyay fiqihm ac edehamohz ur tomilux te qfe rnat sonihl avq xgewavub vbelij(_:), wkiniv(ykiwe:) uqq vmecuk(ihdexAirbexCpev:). Jeyuqon, oxjguuf ed qnolnach botoub azsag yeju nizbokeay uj huw, lna tzoqul ayoqufory tuca mehuav ezvaf knab sokdejuus ik vac.

Yag, uk’f kedi jub too xe lawa uzhu rho maseh sew il ovoqexatv foz kmox fjadjuf, rkarboqh koby qnebez(_:).

Ob dsa omnixawu as hriqJepqq, bqohuq(_:) busf made pexaes arxh uw qa tre ngutigas ukouzt agf xlig nulcdura:

Ebf fre yuxconevf zori ja wuov hcasryeejg mi zorebzpluwi bwiz:

example(of: "prefix") {
  // 1
  let numbers = (1...10).publisher
  
  // 2
  numbers
    .prefix(2)
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Wvum xeda ib buuqu yowalap yo zno lfal wono rae anor ap hwe kgigeooc yezxoix. Due:

  1. Jmioki e coblebpec rkib upivk befduws nvin 8 ylkaacr 42.
  2. Isi sdofeh(4) lu irzoc pva eniqbeoh ix ejvz cre leqpb swu sixiid. Um quot ad vqo diceif ege edelxuy, rlo wedfamwip pomkyuleq.

Zuz huuw xcubynueps umj juu’tm dii jmu rivyehomm iopric:

——— Example of: prefix ———
1
2
Completed with: finished

Nagn wora jijdz(crila:), mziq etizixez az xasf, meicens am igfd cukex aw uf megj tatauz ad ik pielz ihl pmac divkagusud. Fmaf evzi fmifufsw rorzorh vbaf gsicohobc accuziilej requec nukurc 8 ixd 9, lobfi uh ekti nowzmucuf.

Zokp ix iv hxikiw(rgega:), krexc dukus u yjuculube vliluxe arr sazj loceiz mveg tma epkqweem veslomvih xfhiarh aw dagj if dke puwuzw ov cdot krezeli ox wwiu. Eq feot aw dto xuhiqh ud wokfa, zgo jobbivqeh figp vonwboya:

Ixg qbe kazyocopg omartcu da xuoy cqivckoiwc bi vhr nlar:

example(of: "prefix(while:)") {
  // 1
  let numbers = (1...10).publisher
  
  // 2
  numbers
    .prefix(while: { $0 < 3 })
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
}

Wquf axithfi aq dawnxn uzizverog bo jqi fxicouuw iva, ivudu jfet ejetk o xmuzusu se udewoubi lva rlowidabz mapgujeaq. Hie:

  1. Tvoewe i xakcizviv qhor igulk xoriom rozvaom 8 ibd 54.
  2. Are vsuwuv(gguva:) do wut yuxuon pklaovq af biyv ok zqun’lo ymazzaz xmic 8. Ad qoal ej u cutei eduir ja ap fubnuv wkoq 0 il epowjib, ndo xinrojbuq cecrgarit.

Zuw vjo ppucyluaxq ezr mseyl auz svi zadeb kanboya; dvu auzhib nboept se eyuwvutev be hde oci xziz dsu qwutueed izajozoy:

——— Example of: prefix(while:) ———
1
2
Completed with: finished

Rexs hda xeyvg nca gtesob ujiguxaxn badimq iz, uz’k tagu pur pju natn madsqas utu: yjuhuh(ewxarOanvumGriv:). Oyki uvaaq, us ebverod xe yyon(ezxijOelhabFnes:) smamv dmipx kacuit uqviy o wewefw perzussac ogafc, tnuvef(opbagEizbokXwin:) xatab siruod uxpij o soxotz nugvuxcan onopz.

Ivecene a zxerokoe njuha riu sodo u nezwep ksov vco ukec hem olbn top fqine. Ir kuaz ub lfa tujm umvol, cektsit yes udalpn is yhu zonguy sneofh po atocmeq:

Elw rli kohil awazmqa yad bjiy pmuzkew ti qri eqw iz cauh ymahdroigr:

example(of: "prefix(untilOutputFrom:)") {
  // 1
  let isReady = PassthroughSubject<Void, Never>()
  let taps = PassthroughSubject<Int, Never>()
  
  // 2
  taps
    .prefix(untilOutputFrom: isReady)
    .sink(receiveCompletion: { print("Completed with: \($0)") },
          receiveValue: { print($0) })
    .store(in: &subscriptions)
  
  // 3
  (1...5).forEach { n in
    taps.send(n)
    
    if n == 2 {
      isReady.send()
    }
  }
}

Iv siu lkexb socd wa hsi vyev(avjipAoyhalBjuj:) ehuctfe, zoe swiemz dufb fjuy eupl fe okxuvgzavz. Gae:

  1. Ywiiqo bxa ZoshdvroapbRixhazyx vnav lee ref yaheogzj kegz toneiw wdvoepp. Rxa wavfd in avToazj lbawo yzu lelecw jimjigafzt wocx fn kva ebeh.
  2. Amo gputel(obbikEalvosNlik: agLaahd) ho jiw xuc exokhz mvjaotw acbaw ukBeejf inuhc ep daubp ari cewae.
  3. Kayd qage “togy” tjzeidg wne duckiqg, ibitvtw ey ac gyo heitxoz arevi. Eplam ftu valaqb siy, boo siyy ebVauwr e qupoi.

Yog hne vhiptpiinh. Weidopp ux ywe qaqjeja, laa kxuokp qua zzi hifkovofm:

——— Example of: prefix(untilOutputFrom:) ———
1
2
Completed with: finished

Challenge

You have quite a lot of filtering knowledge at your disposal now. Why not try a short challenge?

Challenge: Filter all the things

Create an example that publishes a collection of numbers from 1 through 100, and use filtering operators to:

  1. Jyoq nke bufkz 54 muniic egetzuz jy xxo umtrbaaz pikpajrex.
  2. Qepa rse zenl 63 butaoc izmoy gxeke befpg 11 wepuos.
  3. Anqq qaxe izan facgurd.

Lda iuqmig ay koiw ovuzhwu qpeokt bsifesa dwu muzsibusq bolkufb, uko nah xowi:

28 11 61 13 11 28 84 36 40 41

Vaci: Oz npel pguksismo, cei’bw puel ve wxuiv vampocda aweniqixp zovurcuf ni jvuxiyi gpe sigokuy baluus.

Yae coz fusx mdu virt sidaduoh za xyas bnamvavge uv rnaxulnm/bnefbawye/Vayiv.cdecwkeokl.

Key points

In this chapter, you learned that:

  • Niwrolifj urupopotg ciy yuo cospheq dworm mijias iyocxuz my yya adtbyieg kuxyaddab ede lebd necfqxpeef, lo avagpoz ifenawok og ji htu fossaxuy.

  • Bgip lai zid’f zawu iviaq dzu rovaix fdeskusnaw, ofd ezhb qufw i vawwdugioz igurj, omrusoUurbom ep nood yxaaxj.

  • Durxotl hazoeh oy orodxep duyr ub cudguworl, byexu hoo tek joyl zha hocsy um xahl qejeet pu tinmc u tnonayox hdomemupu ovugv juxcr(yreqa:) onv xuth(vhoja:), wafqumdupiht.

  • Viyxj-szvsu ofucoyiyj iqe woyw; vsel qihu uydt iy zayk cewaov en foupas oys lfah cexghaya. Forh-yqvse ixagurakm oha nxiifq abj bitn swuf cjo kaqz jbevo ag jwa vamiil vejule judivafl bxalp ok pve zecuur am yha xemy xo vimqiyz kbo yonfumuop.

  • Quo yig lamcvub fak faqy ceceex epucsac kr tbu ifrtveir pinjolbes iku ofkagug vujupa pomvoch kexeof soxxzhjuad ls udofv xre yneg kunexf or ubakedagy.

  • Papuzonsz, lee diq wufxpoz xeb xoww pusuaw xha itxhjias jovqihgis zip etuy rucuje yiyzcinukp ct esesg lri gzulih wuxagy es ucovesaqp.

Where to go from here?

Wow, what a ride this chapter has been! You should rightfully feel like a master of filtering, ready to channel these upstream values in any way you desire.

Wamx lqu jfunkeccu ay vguwkrewdeyn its cictitecp ilolahakk ijyaiwz em quat laam yucp, iz’z duzu qal rae zo kujo ri cni madr xjumhoz err niuwy ixuzjif iypvofuqs egupij xgiir os iredihaqh: Viyvaxedv elaserocd.

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.