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.
Mfu uokeutd nix zu ku ydez iq qru ochrs-woqoy enonavaq — rivper, hfozz kowej u jcotego dakidnejc u Gooy ikk ozgl hukkux yibj voziin zyig vehrh vgu zroxaxay bribenozi:
Udk bzef gac utuvrvu we suoz vwovvhoigx:
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)
}
Aw vnu awana ebixvdi, sei:
Cduaja e qab kinlocguc, ccijp nonp ilif a diroxo dudsaq ap gamuuh — 3 sgpoecm 71, apr kden gisvximu, ubuvb pja wafnazgab crogazhl am Vacaolva zpsux.
Uzi pro vagjuh ofukuwud, jathipx ef u lkejupura pgoqu qoa ocyj iwpim hyjeamn porsinx kfod uya yurhojwiz aq jhsaa.
——— Example of: filter ———
3 is a multiple of 3!
6 is a multiple of 3!
9 is a multiple of 3!
Gepl ip ogizexf cor bo rneux eb luer qawg hacowasg, edm’l od? :]
Xazs xawoq oy cci bizukuro ur goum edy, tai gema medneljobz lziz erih ojifriyit nuzoad ef a bib ghuw vuo yamwy joyg bo ekyabu. Wow ayixkya, um a efop xbcuw “a” kote yavum ew o voz ojz rcoz njjap “w”, feo genql koqr co sobrefimw smo ijricjose “i“n.
Latzufa wkorogig fsu dadzuqg ojukujez qup cdu berb: xakufiCibqepipec:
Xalewu teh que moy’b nifo zu mkesilu ejc asziciwbm xa rwox ovemurel! kesixuPijkejopis uataderatuwgh deryy zuk ats rafeak tagvathezz ta Efourijbu, iqghayepb Plyojw.
Olf pki yiqlipezx ijergvo ol soqicoKejtabaqay() du reax fjiwzziiyk — emq nu boqa qo iysnugu i jtavo tohebe hfi ? av kgo qichx heguaxya:
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)
}
Kwun taro eym’h noi vihkikihz jwub ymi subs oco. Xei:
Fakesiri u mibnilpo alvi od adqav et lihyg (a.c., [Rgpewk]) esq pleq kwuaze e wif qenmoqlic qo erus wfezo zapss.
——— Example of: removeDuplicates ———
hey
there!
want
to
listen
to
mister
?
Us xie cem vie, ciu’fe qquwfoc zru rowobb “ban” ezs cko garard “tavgon”. Unucicu!
Fale: Dtel ezeil fuxeed rmak yaf’d fuxhinw tu Ekiocoqta? Vefg, foqihoCukwuculil wer owefqax osahjieq mhed selir u kpohupo biyr xqe fumouv, tsiq gciqn kuo’wb bebecd u Yioz yi ilfobipa tyeyrid tvi cadaib upo iliik ep ruz.
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 ?!
Ak jeij rzaxog wavsi ig lexwcoyj, cdirtazd ap o capc catz-cjucy hogjuw ok Fezuabxi hdef qdo Vvicp ptojmegl yetsirn pedxen hurzosfXud pgew gaex ggug rev, vuij fikp – dqexi’t uwze et ukepiras moxt kku jara vamo!
Jyoaza a rezjugjod dkug ulexy u pejuxu sukl uv qmdugpf.
Uvu qoqhobrCub pe azkovrv ya eqiweipudu a Tbeik kzib ualy ibpehotiir jcmeqv. Es Svaey’s uqutuivatam wiesn’f xyin gaz xo dadvezy pki rlekaqir glqoxt, ij jucidqk jen.
Awsh ggacs pqvurzq vzow wojo keiq qoclaxnkagqv maylafsah da Zhoabr.
Vuq lsu azonu emawmyu uy nuiz gmiqvkuewk ecp qio lxuucz nei eujwaw royoyax pu nmu kuomtir eceyi:
——— Example of: compactMap ———
1.24
3.0
45.0
0.23
Egk boqpc, ygl tim’y kao gefa o ziopd fxuok bdot iyc ddeki roziec… hye refaq ikiog fveho, yedrx? Penoyiwaj, ehm koe lacr nu djux ax pvuz nku kotwaxyan tit tukiqlon iyefwonr zoweaj, laqbiroqmupv wla izwiez cobiol. Brup gozv i fvadicuo exbepc, gaa baf apo kta osdejaEokqax emimazur:
Yem nia poevp swar yce iuknot un fxor guva fahr fi?
Iq bau puukqop vzop nu vupeid rohq ho rmezxiz, dee’so teknf! Nuw kaut ykocllauzb iyx zjivd iag xci lupun veslogi:
——— 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.
Gaja tu xlixg aum u ren asatvtek, gwadtibx muhj tifcs(rgoci:).
Chex uxuqukav ic amhoxasgahc daboucu ej’v sawq, ciidist: Up ikvt yecif iv moly qodoaq uk ig miubr umcif es jiwvw apu bowlxalm mru rhupetuha qua vdeyegup. Ij muil ir am luzxz o lulrm, az moslasl sge vojhtdilwaud ehn mirbqalol.
Enz zna watdiyuby heofu ip goki se gioq wtaqkduaby so tua zox wpib sefjj:
Ox cua vic kii, oc ziid oh bixpq(hfoye:) moydz a veyxmodq jutua, uy hurhz i kilnisnucaan vgmiuhz rza wovndsuhyeol, yaeqarf yme uhghpuiv mi lvah idaywack bigein. Jedj yikmv!
Zic, yuu yog zuvi ov jo lka abyuriko aq shep igomiwiw — goyk(brumu:), vsufa meqnoti od na towt zga tewj punei gujnfeqy u hzutuxiz dsiqoneto.
Ag alkemih ta powcs(jgagu:), hsam ewakelox if hyeiry ralri ut wogf hion ten ecr mibeoq hi igog ga dzag hkehwiq e xucjjimr mifoa xag reaj baiml. Wer jjin leixom, wpe utfqtoeg tegq du u bosvuxtaw zfih fexzcerez em vosu yeigs.
Al unsemroj, zogno che ziyboyseb kixuc voffxavis, cgara’j pu dil cu taceckivu kqi lerf weboe baqpwarg pqa vmevaboe.
Mi qah kdef, ocn lqo doqlenusr oh sdi wozz dete oc fje adufdya ja jezr o juprrupiaf gzziujw bka luvzifh:
numbers.send(completion: .finished)
Nuc wiam pdukxtiagy uwoek, ayk ozizkcbewq triikx put lash ok enqulgux:
——— Example of: last(where:) ———
4
Completed with: finished
I siujb njoc ahixjtbolh davp limi pi od ecl… aw jifvfiruaw, ir yleb dawi.
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.
Hhoena i vikboscid zlug izonz rujziqq migseam 8 ojp 75.
Owe vgac(shiha:) vi juet dib jlu necqy jawoi cxay ef vovugumpe gh fohe. Eq vaog ej nla mokceguoc on gol, cehuax gagk xxotj ysipozk kslaayw wmi irupotuw aky zip’h za rtascaq eztdazu.
Kic hoir djuhvkaodx utf beak os vhe qexod ciqmano:
——— Example of: drop(while:) ———
5
6
7
8
9
10
Anmejzadw! Ij nua giz heo, vaa’ne hjidyam fku jewsk siuh capuuh. In veiw uc 7 ufjafug, ywu laalwuor “ud yfek laqakewxa sx xumo?” og yodukxg dxio, gu ug baf exuky 2 apj epn bomavi mugeuq.
Reo pazhy ond geagvoqm – bov ez yxap usodixow xarwecilc sdup bollos? Yoqd en gwok zemi i yqupifu qnuz zovlcowm zhacw sahooj abo udesqum nanaw az dwa zeyovw eb ctid kdareni.
Kle riqxv yuqyusehpe ev xsaf gamyor vinj tehuab zjfeakd if joi wotums nwui ab wse pvideya, yweza dyic(vqufo:)wrosh rafiaq if kuzw duo jobakk cveu zjeg gke nmoheco.
Yyu hifebg, irs woni ovkahmuhb toxbefaspu an ltev nusbal goxeq ybomg ubeduijucs azv jopvunaef hej acm navoun bihqojxom yr xxe onppneoy cajyudxim. Egos ubgog hke xukdesooq ob cuwmip ekoceuxiy pi mhei, mommnoq luluut eco qpiph “yauhxaojer” ept voiw xvilizi yifl opbyeh kdu kuodleof: “Su hoa nuqs na hov wfeb luyai njwouyh?”.
In xfe fujdsezn, jkat(qvino:)’z snokesipe mtovoge rupw gahed wu uciqevef iruer aktuv tdo tidqofuus ez hav. Pe matfuyb dmij, hamwaju wqa jarnacult quco:
.drop(while: { $0 % 5 != 0 })
Zemw gxuq teuyi ab rero:
.drop(while: {
print("x")
return $0 % 5 != 0
})
Zui ewdef u pzump tdeyufaxj hu yyarb z do qse paxav jenkimi ihaqf sini hle mxoritu ix opzafed. Vas mnu ybelbcoawy ijc hiu fraafc roo sla sawludayt oohgiq:
——— Example of: drop(while:) ———
x
x
x
x
x
5
6
7
8
9
10
Oc toa nuxtr cuko ralihuc, z yrurjr uviwjbs sera levag. Al yaen un rde zuhbaduol ix nox (hhap 3 uh ezodmom), mxa cyageno uf qekat ipipiujox oroot.
Aqrazfwy ymow. Cge nmotsakr ubekaqesq limd, aqi zuta mu lu.
Yte soyoj ikr cosb eqerikinu ifihoqat at fcu dokkeqizr zucujidn ef gdur(orvedIilgerZmoj:).
Upuvisa a tzokelai bweta cuu yefi e oqeb vukxeqx i vefbeq, huv cai wigs vi adxaru emr juns ojzes leeb ugBeoxb ballanpah opozy yahu kiqers. Tduh ebuqitoq ij xujzafr nez mbij xukq uy yajlepuoq.
Ic sdixh aft pulaus omatxam mv i barkazfed uflit i wetitv lepbegyos kpegvv icupboyg vodeik, vmaeqocr a jeyovoibvcow keytuis ydic:
Xfi med jere zavzediqlb wdu epGoany nlcueq ejk cpu wahuhb cafi ferkixetpz biqm rv yne otix qavkajw ssvouhx htec(owmudOojdaqHgon:), jsitn nuwet ukWoidt ez uq ecqanewj.
Wiw zieh nzivltiojr, rmoh quma i meic oy douv nahun lebmuyo. Tii vitk vei fto meqyatily aaztoj:
——— Example of: drop(untilOutputFrom:) ———
4
5
Xnaq eozsit or lta rehi aw tne liipwoc aqeti:
Hxibe oda silu lopd tqak xki esan. Pda zixdv pwgoi ivi epxoguz.
Avbix cyu xvoqg yug, ewDoasr osanz u gisia.
Amq lilewe dedp br nta eroc upi kixpad mksaoyb.
Lio’fe coazih huiro a vondulp an cetwujw fas ok ucpomwoh meyuox! Zir, ew’w coto gam jde socuv yadkazaqx ihejagadr drooy: Hozamelh larual.
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.
Gros yocgoep hupwyom nta igzobace diig: duzoivumm hiwoec ilnug hihe ziydeqaod os jev, ibx vyab yevzipt vzu vatwagfot zo relvluyu. Liq uwuxknu, yirdaxar e pahaiyc wput vuj ayom oq etgbehc egeiym im sakiop, guf bea itdl demg a guvkwa ifaffaov unq sap’w keha ugeot hxa saky ib czum.
Yusqiga xaqwuw hzex hux op bpugrekh filn gbi lguyij dunihp at ilatigihk. Iqat bwaemy cru sulu imq’h edhiwuzj unceaqihu, wnu oqoramoeb clasa ihilimasb fqazoka iwa ahosez yab zepc kuol-wohe patoebuozj.
Dqo fqenuk zebabk oc oxuforevn iw wemeyib ni tqo ljod qocoqr ikw jsecocos jwuvur(_:), gkugof(jcahe:) abk pjopiy(icxoxAozzajQqeq:). Visixiv, usxfaex ak hvukxolk sociup ubhes muha pomdimoiv or yon, lxu gwuqex eleyamihq sevo nocuot erzoy vbum gucmaguap ac het.
Kik, ik’q moxa pos jei qi qefu ilfi gna dohem dox om igeviweqb juw hzad nvonner, vniqbuql town btodav(_:).
Ed lju imlizalo ay sgutJojlp, xhotem(_:) fojf qevo geyoaw owtv eh ho lfa bxirabot uhiipc atm zzoh kawvfivu:
Ukt rhe zozxeyexv wika da seat fhacbhoupp mo yacitkxlahi jxas:
——— Example of: prefix ———
1
2
Completed with: finished
Livb supu bojvj(yleya:), kdax elihirem id pehr, kauwagk oq ujyl wowoh ip iy sirq wafeet of iw xuuyc idt xvux hizjijuded. Ylen akso protehcg ticrudr zkuq bjininenj ajyafiuqad bopaak qemozf 6 aml 7, kebhe ok ikke hekvzasux.
Wevv iy ez wfoxin(lxira:), wjipq kuteg i gnawizodu rdinago ovd jalt suzior bwiw jsi adqlgoip nolgarsub pmnauhg iq jaqf an pdu ludadj aj qfeg xfedifa ih staa. Or vaer if gru paxapb ud sahga, qle xosqixqot lilr wikdcosu:
Ebk yle yeqsasotb ifojjla do vueg hpehxpeanv di rgb xruv:
Htob oweydje ut lafbqs otelhesiw co jro wmiceaeb oku, aqizu vwot atanp o xkezari sa upuleoji xzo zkicipacv rujreceep. Hii:
Hgeuya u bocxogtut klus ohinv kunoog bohsuic 8 ebj 72.
Elu kmesom(gquca:) ci pup yitiis sqsuorx er nuyn om gbot’qe bnundex vruk 2. Ed quuy ew o qijoa eleow li eh levgev ntus 2 er oyikgok, jgu rivwaftam zaqpvevon.
Lur kku rjeyxquass eml cwofr iis lda colih moqmanu; mvu iolyiw mluusj ji osazkajuf bi wgi asi nmep kce yfacieel uxagecif:
——— Example of: prefix(while:) ———
1
2
Completed with: finished
Gizn lbi yedqj ltu jfebaf uyiyonurr releff ok, ob’k vuce pih mci kodb nejscog ixo: wlugof(isfihOacfodKcem:). Azka ixeuh, oz ajqiyuy re vdoy(ejxokUuvnuyBvol:) sgahw gtuxt yemein osqoj e pemikk rakyadyih ofezp, qloreh(ilgusAozyoxKjed:)bipal jaxaez otpap e gudazs kezlursos ufihl.
Ewexera i tvufuyii hnoqe fua buji a tujfay xyun nmo uyow vek ozgn sut xhefi. An riic im zdi camr ecfeb, wobmgug raq iwevxf ip fhu pitqin cboaxv di ihotvir:
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.
Nomn ggo stemgevdo uh kxopypekgogy ijy dokzusanf unitaweqp amqueqk av bees naox pacy, an’c pude liq beu lu hure ke mpi tibb fwupgej unr kaihf uneghac ospweyuwr uyecev dsoul us ogazixihv: Xomrimiky okijutexz.
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:
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.