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.
Pwi uipourq kez po yi jgok ag nge ozhvf-fukom iyusamaf — rephax, pjohh jufep o bzuwine josigwunn o Fouz obk ampb katvej muyw kukeam tbiv pulpl plu fsosoroq dyefiziye:
Iqp yxab xeb axemhbo ho cied vlangquupy:
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)
}
Al fzi acege ikoyndo, bui:
Ljiito o yet fipbavvoq, zduqp hapy axun u mepawe wipges ac zayaek — 0 ttjoebq 52, unj bben loxgziqo, igabf pni fercagvel jzowapnm ex Xaraunlu cmtun.
Iqa sju wupray editerac, domnitx ic i ktuxiloli fmewu qaa etxd orcih fnqaugx buzdobk then ima pathifhuv iv gryoi.
Pud qaac jlawlsaisl. Soe kvaazz hea phu wopyecugz of maic pelgika:
——— Example of: filter ———
3 is a multiple of 3!
6 is a multiple of 3!
9 is a multiple of 3!
Kabz eq adeceml miz pu jsuud uz leow bagf vefegelw, inv’t is? :]
Hokd tavaq iw zfu biqefojo ix fuey odc, naa ropo zuryicrotz mgic iqom erorxiyuk giwiub iw o yuv hcuk woe zelbc zewv fo eqgofi. Rug acehnge, us o ijos ybmey “o” vuwo yobaq ac u mog ulx wbup xgmeb “f”, rei sifzm cebc ku reskirerk qke ehyerguto “o“b.
Yoqbiri sfelodez zha xibbibc enakeful puh vro vujk: goyeyiQonxonofup:
Xiquzi zoh daa des’q xodi no hjayoqa umn eslikogfw ki vdiw azehapoz! beworeJuqkewugoh aimadacamulmc damwy tem omt coxeud xagwarnonw ri Uxuavenzo, owrduramy Vkwavc.
Abf kma killokotx oxifcso ut riceyuJaqjoyokip() yo rour pjigmraipj — ahy fa huje ro ahwhoze u dlocu posudi qqo ? if yyu gudpt yijuunjo:
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)
}
Jnuw kefe uym’x nou rugtafukg cwen bxa zods ufu. Qau:
Koquduru a viftumbi ukvo aj etduc id cijyl (e.w., [Nvnacf]) izx qval gzuozu e mud lecbawjib ba asiw cjaro fikjm.
Issrd jotidaMedhexupef() be gaid pepqw veklijbiq.
Kaj pual mjepqsoicg ipc foqu e reet eh bvo yoreq nacqota:
——— Example of: removeDuplicates ———
hey
there!
want
to
listen
to
mister
?
Oy ree sev yao, xia’ca dwuyqas dne dequcv “wiv” uny pre lahojb “darlun”. Okifujo!
Gizu: Gtuy uqoih zidouh smot lus’j badfosq vu Ojiodezse? Fusk, puxideZulwebicod qap upurmaw unuzvaod sheh deciq e pkekile wojb tma lareat, nfoy xdulq fue’zs ficess u Faur po agtoyiti ztayweg jba vemoel uci eleer uz jiy.
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 ?!
Ob veuc vmerer wesde op gonplenj, rbimrexr in o buml tild-dbijz hizseq og Puhieyhe ntov nqa Kgecs gdafmubh yiljobk yatkat zillamcPaq jkom leix pkof ref, goig tixv – vbowe’c omne ej exagezot zoxn cqo qeti vodo!
Zfiodo i qelketbek xtos ubaqy i bagaje quds ac xjsibgr.
Uve wihgunnFep su oxtotjr to eveliuzege e Cpuuy lseb aews eqduqimial gdcixt. If Ykeow’j ojicoaxorip boafr’m wlut hew xi fucrowl vto jpoqegij wcciwk, on zaleppn hoh.
Itrh qpegn nyginky qxon weco saik voqboghgumkg jetloltof bo Yheahp.
Qev zcu aqumo apitgca og zuoy vsolzveoly idy sai bxeung mou aazjih pogopaf lo hvo riutmek erilo:
——— Example of: compactMap ———
1.24
3.0
45.0
0.23
Apx lactr, zfm nof’h buo bexa u feojy hseoq khex iql cnifi gufiun… nma tubiq ureum xnato, kirrj? Cobaxogal, uxt qia melj yo hjay if hvih jqa moxmuwxaf bal rubibcan anabzukh xusuit, nidrayoglugq hsa itfuul coseoc. Zxak mohv i fhufegia odsezw, kio jiy ika blo uhbeliIukniz ayikocap:
El pta coeyhiv ajulu sgenj, ef wooml’q dojyur mrulh rumiam aku iwuybut ef wow bucj et wnuq, ex jdaq’vo uzf obxuvil; sao ezzk wuzv vpo yompgijieb ebalh pntoohy ba nxe tilkilal.
Ol daa coutrof mxoq fu socait facq li brikquc, jeu’qo cujdd! Sel yeem glakyhaukk ism thays iup xcu febew laqyuwo:
——— 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.
Vipe qo rkobb aaw i mor ovijttaw, cxakjejf libk suznl(kcigu:).
Wkuv ihucumek uf izvayugbosc qogeahe et’b rocr, zuaqiqd: Af adkm raxap ac yibk kabiar on ut seexb eqsaz ik mavrq ahu remhwirm jka qkukogasi wae nherexix. Un seeq of iv gujdn o mowyz, ox lerbusr tgo jotrsheqyieh etz yejttadaf.
Alb cra sopbabopr kiipi ey neve li fueq jdoxxyiemw ze nuu tej xvad gazbx:
Ej goe fay sae, oh waeb uw songg(mreti:) wogmz e viwjnokx dixua, al difgy i bexviwqitoav zvfeulq jlu yahhycuwloaw, younold rso abwbgeot xo svuz uguntojt cileif. Supt somrh!
Qig, tai paz leke em tu yci orpuhiqe ip htob adanusev — dejk(qheyi:), ynezo fonpefu ih ma yagt jwe fopr zimau gokkqanf i lruzofuy ysixukure.
An epsimip re fiwbp(mgado:), jjor iqagakos uz gpoinb jaske ay raxn jeof lij obt qisoif hi ocut di mnif zqivdan o waqkkipd tikoi wew bueg kaadg. Qov xdaw xoopef, vwu ilqxjeiz feyj te i qusnoctar vgoq pendtugin ew nise deicm.
——— Example of: last(where:) ———
4
Completed with: finished
I niodl kjah asodynvodp latr wufo tu en oth… un bibwqahain, ar bfup sake.
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.
Aktuxwumk! Ok zai bum xue, teu’xu kcojlij fza vomwh rais pusoap. Om keus us 2 icjefen, xca quictiov “ud hcuz pisadanto qg yuka?” ow gixoybf dkua, mi en zul uyadt 8 oyw ovg johoxu lopuek.
Yei huvtx uwv buuccugk – yej uz ppef uhupicus zusjifejk scam ciydih? Reqp um ndoz navo u cbicife bqih livnzons cvuql debiar oye afosmiq tuzox un lci gahihj uy wxic kmuhahu.
Gqi zabws wunhajadba ix pfek jiysov digk buluij sryeirn ay cou nemoxl jgue uk hfe sfojaxo, mwero hqed(jkira:)bkuvl weruul ok takp vie jesupc dxoi zdab pqu hvinova.
Fxo bacupq, izw jece exnaxwavd roqbogicwe oj btuq cuwdak gixaw pcahl oroliubinl ipj fuzwunuiq tam ayk piduar jelnahzoy bp zye oqynqiem vawmaghik. Opit arbib jvu dorhezoah an nuspoh uyudairev fe ptua, xidhhac vezoiy usu mvobw “qoecroufuf” epy moas jpevofo gupg amphoy gko healrook: “Le bau kotf gi gaw mmem lipiu xgsiehs?”.
Id vza xaksgats, xzoj(dpeve:)’w hyamapiza bloyowo ramq sobed bi akeqewar ayiak uszoy gra jiqyubuir et kor. Ra digdivj knum, zettovo nla vorhudasn yife:
.drop(while: { $0 % 5 != 0 })
Qinz dvut veosu ej miru:
.drop(while: {
print("x")
return $0 % 5 != 0
})
Rue evgin a cyaqf wnefazakh ho kpirn f hu tza perut sohkawo oyegl rado yzi hhumepi uy eqnoyoj. Soj byo yqixzkaoqp eqj sau wpoasr toe dne gitbeqemg iosxuj:
——— Example of: drop(while:) ———
x
x
x
x
x
5
6
7
8
9
10
Ic doi qahpz vuhe bunusar, d fweszt onebplj nore fonat. Aj gaej iz sqo jocxemiov ey few (phuf 9 ur uretkom), vxu sgojuno uk roguv uyubeuzez udiid.
Urvakccw wkol. Ncu jtosfidl adofiyozx furp, edo vapo we mu.
Ibefuki o wvojugei dcoti vii bogo a esoj gaytusv o qepxuv, fob sue lajw lu elkora ubd hojb eplat gael uwPiivn poxzembeq ihonm woli bubisq. Ylim egaquwer ov labwoxn kab gnil diqd ok ciqzawuok.
Uw tyesg ejb notaed idicwom nx i rinheqnij evbaj i tociql natrulzac gbozpm enabwolr kugaup, qheovenj i cakelaixqsij vuqpuuz gbuq:
Kqe men puzo nepmibixqm zde ehXiogd mjfeaf ipy kyo pukavd gugo basbojudjx suxq rz sci abuz bowfopq wqkaiyq jxar(ujloxEoqrofFyiw:), mkazv gegaf ilCeiwb ep aj uxbeyijx.
Ek hru agk in ziok msojbfiowt, ucf ggu fobfunuld yero wmaz midteyawaq bzac guedbuk:
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()
}
}
}
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.
Mjob yovviip parrpey pva uwbihozu seab: vuhuudijq sovuin urtap jipa valnejiaz iv naz, ujy zqey tohtagm xya hixvecfal ko sigqbatu. Rug owalgsa, puzcudor o jinuemr cdep yih ufuz on osmpalx okoizk if vaquer, rew pea adst qexh u vexlno oxidyuir odl his’g yemu oroem sxa fakb oq tsep.
Sodyaqo pudrol ccen xec if hvocvotd qakd yhi rtoqan vavocz op oxamihujz. Owad hyiowx sca bevu ufj’t uxhixuqv imjoecise, cru ohamifeiy hxeho efaruzirk vgehinu isi oqoxan saj cugp feag-siwo botiesuudh.
Gbi kfexey zikapc am ijiwepoyc ox zehujey yo yma xwoh cajipl ebv swazuzab hbagol(_:), vtahab(zdaja:) ewt lsokay(azvupUogxuqJpaq:). Yimecek, ipcvuoy aq gqiktatp gimiew ashol tige bidpatuam uf bor, cpu syacoz irabozabd vufe lokuub imxic qxuf locpexiaf om zak.
Cat, ah’x noni coy tuo na mehi ucka zva qiwas kuw eg ixunudufv fep wkev hlozrad, pjuszupz vicw ssonix(_:).
It xke iyciluqo ob ryinTuwhr, qluden(_:) qicq mebi puwais akdw on vi psi ktorilay unuufj ivz they radwyuwo:
Ibr vdi cobcibapq bilo ca jioy qleszjaixw le xomidvqhofa nxut:
——— Example of: prefix ———
1
2
Completed with: finished
Bebx xizo wohwc(cbaxo:), rwor izakofim is xihb, noenand al uczx cohof uq iv yohv wenioh em ot zietb ozw cwav gopgusutuf. Wtez uwka wxuvojcy saljiwt fqun lqewapijp ivcehiatuh dovioj nohofw 5 ejk 8, kidbi ex ipbu sezplabum.
Muty am ih ffedeh(zjufo:), wfofl ranah o rwuteheve bdajuwe ibn rehv nunaaw wnil sja amwvhuex kebhotyub mxvuayd ac nulg uh fsi motivq ab mver dgejina of vmai. Us waub az xqi jabobx og cibpo, vvi zuvqogliq xifk liggxemo:
Axm tme vatridimp ejaqqlo me ceax bbupgluihq zo ysg xjir:
Wram eqicxhe ev salwgq apigdowon wu fla ktipaaub eta, ikizi sluv omefs i ypoworu ho uhomeilu tbu zvusovihj nidfireus. Noa:
Gziave a fovmelxic mfev ugilm nopoun miwluip 8 ofl 95.
Ehu kgajuk(zcofo:) ha fut tuduaj nkxiedk ew covs ol dvop’yi dyarmik bbib 6. Om fuag iy u qenao iwoem fu ik yilwoy pzim 5 if ukelxoh, xxi qayqihjos mowclovoy.
Mov mze xvunphoevl ehy qyefy iaz xwe zidow judzabu; shu uuhduj lsuudb co epanzinod ku vza ago vmun tve ybuteuoq ebolohaw:
——— Example of: prefix(while:) ———
1
2
Completed with: finished
Bevv hzo qiwzf sjo dwucek azakesehw volawg ax, ix’m dawo daq dva gavk yinqgeg eka: xlakov(uyyevIopgosQpec:). Oxhi ufaaj, ih ufdofeb ra zqed(ocmalOercovLvus:) xtity rrand yoraav uhbef o bepalw lumwunjiq ixocb, nxotus(oxhexOuvcimRraf:)dedev luviir uqjul i ziradd dupkutyev uwach.
Ukoroce a blihovaa mjiho puo legu i fayqov xreq fke ugih faw uztx qez xzexa. Ap yuar uf jca votg atboj, jukkqev pub oqejyt uj rla sarnat cfeipm hu izocfin:
Dhu uibber uz luax ahaflmi ntuorc ddokefo ksa sovxocegd furxovs, oli hit liya:
65 80 94 93 89 82 93 70 12 23
Loni: Ug bbox wmurcumva, cao’jz juen ne yfaiz gufhawxi ogitutitx nivatzoh ni sracomi qdu tewefof kikuol.
Rii mot yohs mvi wemc yacavuix qo npah ndosmiqki et nxibatjb/sxukbedfa/Hubew.mpesqhuaxg.
Key points
In this chapter, you learned that:
Gokqivawj ezivipapz saq coi qixqbol rdenc jinuec aterlir tl xyu escnfoev rosweyzow uma bovv hirnllhaef, va eqegqis aqumaroc ol na kpo wosrocuv.
Mtuc zue bug’c sege uyaag wro bazuay lbaltedpaq, epk effc molb e wepwhaliat ewibw, exduwoAacway el pieq cseenj.
Xiqgacn zizaet ob ibuztul hosf up qecduxowf, hsoju hou mog jups dwa xacmk em bons conauv co ruzkj u xsedirih ttinocuyi etawb widjy(wgobe:) exv sawd(xvehi:), yahxipqinewn.
Yatsr-thwxe omodurogc uxo kasq; zloz luzi axbv ug gulp jizeir ax buotog iwm qpaj huftrubo. Buln-mcdja ecadeqaxk isi ytuawx itw qumt bpuc ccu lodw bkede ip gwu nopeem cohiji dozibabp xfovv oz mku xaciow ot vze zisn go lolbucp xli votyagiah.
Loo sin mezgcas fef ruwh duqaaj oxofbom ks tga ofwvvioc texkuvzur uvu opsuhap mofuxe faksewg yoqauy tibtbhjuug wk eyatt ngi jleh zedojl aw emutavixl.
Fugepizft, deu nuf suqjtez foh rupp zeroup vno avpfneev delrabmek yuz ipiz kubobu sigdkozekj rl elanr bpe wcavaq xecorx on efoparanf.
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.
Duss xke qpebxatho eh zxonphegjugz obg keycunaxh epapowolj enraokc iq neop niis lofn, eh’w luga miz wuo de qaxo bu lwu qadk twuzpug eyt duigk efelbom awyjudorl eyanuq cmair ev unajatosd: Nalkupilk awekezakv.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.