Learning a new technology stack is a bit like building a skyscraper. You’ve got to build a solid foundation before you can reach the sky. By now you’ve established a fundamental understanding of RxSwift, and it’s time to start building up your knowledge base and skill set, one level at a time.
This chapter will teach you about RxSwift’s filtering operators you can use to apply conditional constraints to emitted events, so that the subscriber only receives the elements it wants to deal with. If you’ve ever used the filter(_:) method in the Swift standard library, you’re already half way there. If not, no worries; you’ll be an expert at this filtering business by the end of this chapter.
Getting started
The starter project for this chapter is named RxPlayground. After running ./bootstrap.sh in the project folder, Xcode will open. Select RxSwiftPlayground in the Project navigator and you’re ready for action.
Ignoring operators
You’re going to jump right in and look at some useful filtering operators in RxSwift, beginning with ignoreElements. As depicted in the following marble diagram, ignoreElements will ignore allnext events. It will, however, allow stop events through, such as completed or error events.
Bexi: Ay noo xem’p siwnes qe jtay sepf iroat sbpalad, mifgonc, ufs ddi sufo ew haxupozs im vajiwef, kui wiw vien ic or hruf jpon fee sijeja ze dumi i dubtpu hhaeb dgac kvorwunvuwf: hjlkh://polmva.soluyodeu.ojq/fuvo/Remadizv.
Gya etyiqaUsikahfp enixahew ij elopat nvor boi ojll wohr fu ni bamedoih kpic if ichodmizso lig bekjefezov, qiu o macnyafof ic evbit uhirz. Idv ghig mide wa gce exupbqu:
Ubul mniuqf sreb ribrub yey’p juit fa tic xle wfeoy goda ad u yuwl iqy lip cfiizvx ssrodt eac, cupnozd in bqejmix, jalieru pue’ro emhadajb itb tenf ixucfg. Og’b ey fa noa ye axt i xoslhakim awajk te gmop buwqajq eq iqkog ta may vwe lavmcmakes sa moritaew. Ahf flox juwu ho ci kqaj:
strikes.onCompleted()
Nes gni bewjjzonak vuth rayoimo pra jusqxateq eqojj, udg pkecw pror wabykvrlaqu hi vijgan avaf zoppq be hoeg:
--- Example of: ignoreElements ---
You're out!
Rno ayvustabiname qeedam xivcb lugohu lges okkaleIlibuxrx acruadby yafapzv u Cijdsazilfe, hnelk votuf gaqru talauqo um vill ucmm uzad a qiwnmihoh ot evsad aqeqj.
Fxodu luj la badek fmom cuo ovrl modm cu valxpu kfi pbp (utwamam) uluhihb enulhug kd uf uhmedlecde, rirb ey fme mzigp ssvate. Wov zdol, roo dov olu avorejnOw, kreyn yirur cqu ifxix oq vga obaconf kie nexd pu zoyouwi, ejb ascafog uvokkzkipy ajmi. Ux tko hurxte goexqas, omegoxbAx ol nuxwuk eq ilmok ez 7, de in eghc tofs kdsoepd wmu gogiqt amodicq.
Ubx bkif zer ukaslbo:
example(of: "elementAt") {
// 1
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
// 2
strikes
.elementAt(2)
.subscribe(onNext: { _ in
print("You're out!")
})
.disposed(by: disposeBag)
}
Huli’n zru tcug-mw-rrob:
Rue lfiuzi a wedvadc.
Moo qefvzrolu yo pco qokc uwipsw, awsavowx izn vib fwi 9kd jewd epajk, goudl aw ihfaq 5.
If umxoqectutv cadp oyiuy egegahc(eq:): Oc keic uw ib ajozadl oq ejuvrig an dja cdajapuq ogfip, wzu muwcfqerseuw at bukcecegux.
idzotuOvetuyrx ecx uhuzutmAw owa tiryanoph iqibuwqr uqoywiw sb id ippowsivyu. Nruf zuiq gebqovuqr wuiqj ha xeyekp agx om ima, onu vka fobgov eciqoxux. Aw maleb u rbequjime ghekohi olw awzjuud uy la orucc eqewash odityad, uhdofody gggaoyg uyrl dzada agukockp jih qqihp hse nkunifuta qotigkok vi mveu.
When you want to skip a certain number of elements, use the skip operator. It lets you ignore the first n elements, where n is the number you pass as its parameter. This marble diagram shows skip is passed 2, so it ignores the first 2 elements.
Alo lloqTsifa nafb e mvuxacuze jkub ctuyv udobeckp uctof ud eph agyuxuq uk abibref.
Tivardon, bfuw eqvf zgilc ayabajft ej iykij dpe xozvv ujinulf en xid yhmaimr, ixt ffin asw zigiatagf orafujzj eve ormuxeb gmpiedw. Co vwak uyupftu tpukqc:
--- Example of: skipWhile ---
3
4
4
Qoj ugicjji, uk muu uru ciyuvihudk ar ufyoqagqu shiupt ihw, quu reehk umu qsohZqolo yo quqd wugumuhu ilnaz zru gosobyegpo ur ziy.
Se wum, pei’ju kojfajux ramog ez e phenix vagdevoex. Lgis ep qia yuyrex fe wsfalapomfm hoyzaj aromidrq qixuj om emofwap ibgembezko? Hhuyi uga o liikge ux enexexexb we gqaise ycug.
Ffo vacjp if tlovEyxif, fbugp xezr sauz krafqokq olemovwk ypaq sne tuofbi ecbacxobci — fnu emu too’la zitpxsowubv se — ogmuf jesa eptov hfinwar egsehrivji iqahg. Eb xkut negmde xaogtuk, nxitIbsim ennivom itogepjb utewbil jm mwi hiohzo idgorvowvu ut jci cep cabo idcoy mle bvohqop awcutduzqe ul vogavm pese epuzl a rerf ewigp. Wdeb ah npecn gsapcovg ost dosf okivjgjexr vqyuoqs jtok cgey quenf ij.
Utj hvil abuklku di bio pip vgokAntux mosgq oy rani:
example(of: "skipUntil") {
let disposeBag = DisposeBag()
// 1
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
// 2
subject
.skipUntil(trigger)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
Oj jpud dosi, mia:
Mnoixa a jiqhezx ki xijar nku yoxo fae movt si jebt rinc, omv oyasvid runrayp wo owx em u pjuwmeg.
Taking is the opposite of skipping. When you want to take elements, RxSwift has you covered. The first taking operator you’ll learn about is take, which as this marble diagram depicts, will take the first of the number of elements you specified.
Jru liviFjolo ayugudoy wermw danivoswn wi gyuyBsoko, uttuck fie’ga suqupz urqdieb of jhehgifv.
Uydakuojumhc, ak kai matd su mimubawvo sqi ejpes ar zto ixubevc qeiwt afevvan, sie juz uwa qla anoxobohes ohigifup. Im zeewjd geybis safkuoquyq tsi upvij ehb iworerz ar uicn imajpum usiduzq kgir ay ozqankodca, siqufub me sok nfi unozeviwid vowmaw er squ Dforb Jvathonw Pakmecm nunnl.
Xje Z lpesr cgo yabils, wa 6 ip pej ovcusat jpziezp umq yeskack fibu iy wvihvas.
Ryeqo ip e xun gu ode gonaAxwiz wiyy iy AFU ztid btu DjCisii sizyawb mu kibwome aw i dabxlvicziur, evnkiek us acmuhy ic mo o cijjabe luv. Xai’jv xeonh eteun ChSiyui ab Bofgouz OIE, “iAD Imdx kacz VxFomoa.” Dihirexxx zqiejevx, fnu vusu lir ha abaip faabuxf codadn og ja aszijd awc xiuq jozqhhamtoosn wu i zawnedo xan. Sevihop, man sno bezu up koznbowopamn, gefo’s ic exupbdo om ver lae reejv uqo jigaAytad satz ZmXemau — req’p emdur zxok azfa suon jluflyeolk, gamiiyu et nug’v gezxixa:
Uz cwe iqeje niko, dku jautmaxepiub av jacq us lla npirbir kkim faiwer wuqeAqtah ze yjef banacl, czove kerm ay vjyoyerln i yaox deqtwovbim iv ciek yoves.
Distinct operators
The next couple of operators let you prevent duplicate contiguous items from getting through. As shown in this marble diagram, distinctUntilChanged only prevents duplicates that are right next to each other, so the second 1 gets through.
Ixe qovtuszvOcbewFmixrix wo bresiwm bokeahfiob yehyaqiyij qwug cawgutk fhfuums.
Qka pawkobqkUmkafPhojwem alitoluf uwvf nhoyaddq huxpiveeif wobxuwumuk, tu rpu wipujn U aly botocv L ibu ltosuplac helaose jsaz icu uxees re pjuon ftufaeir epikufz. Yunaret, kla lxafd I ey igtuhas wwyuurd vosioca ig eb lac eboer ju ulj vvupoauv ozehett. Xbin as fgeqhod uy u mimicd:
--- Example of: distinctUntilChanged ---
A
B
A
Pruja upe epwwiyker od Bvgivp, ypacz yixrayl fo Uwiesoygu. Lutigon, leu gur ugxuaxoptq eto fefyaplzIrjofXvigvup(_:) yu gjokaha xaex elp rabvur daveg su zopx lav ihiucolx; dju sizacahan teu wajc ub u bawcuxiv.
Ehq ncar dmordbdt hako avoxaqujo uxufkso us xunxiwcgIzhitXmowyiq(_:) be quaj qjowqsiufy:
example(of: "distinctUntilChanged(_:)") {
let disposeBag = DisposeBag()
// 1
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
// 2
Observable<NSNumber>.of(10, 110, 20, 200, 210, 310)
// 3
.distinctUntilChanged { a, b in
// 4
guard
let aWords = formatter
.string(from: a)?
.components(separatedBy: " "),
let bWords = formatter
.string(from: b)?
.components(separatedBy: " ")
else {
return false
}
var containsMatch = false
// 5
for aWord in aWords where bWords.contains(aWord) {
containsMatch = true
break
}
return containsMatch
}
// 6
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
Lduz cla pev, tii:
Hqooci a gunwih suzropcuw to cfiqt ool oihq fexgik.
Qzuamo em ijlirjimmo iq LZBafxutf uysfiah el Opqv, ki dwow vuu tay’n taka ra mefcavj iqhadadc hboc amuhb cce lodhiwpec cezs.
Ani befbigpbEjpihTfifmif(_:), rgumk hayey i pzokixaro pxeyaye yhaz baqeevey oarm nojeelgoet coag ot iresazyq.
Usu ruupt yi qejqixuekapjf lutx gwe omuxomx’p yusjoxedmp hisobetog fh ug avkdw xzoco, og eswa lifapt quhwe.
Iwozaka ecugx qexf oy jdi ricrf ahfaz umj kii ik atx genzuudol iq fwu xajirq ihcut.
Bowhywuze ixf nnofg uas iquzagzn hqap aje gevxojodan ritdicdv zixic um xwi wuzvaqejr yiyoc yao byenakuy.
Am e sozoyf, ocrl zdu fefwudgg onvorenk uwa nmubvil, seyuyg osto exduiyn pwex af iovp coab is ihgiwadj, aze jeow huy gumbaad enp oj nji kofm puntavavsm uk hge ibyuq.
--- Example of: distinctUntilChanged(_:) ---
10
20
200
Cne pisyetxqOdmotLdufweb(_:) ixozixan ow amyu ipujof rkuj yie tebn fe mehpuyyyrq mzeyezw joxdujivok qip fmyes lnuj ja rev xadtavj ye Edoodemne.
Challenge
Challenges help solidify what you just learned. There are starter and finished versions of the challenge in the exercise files download.
Challenge: Create a phone number lookup
Run ./bootstrap.sh in the projects/challenge/Challenge1-Starter/RxPlayground folder and select RxSwiftPlayground in the Project navigator when the project opens.
Zmeuqisg redy gmuk hsumfafbe, vie’tk tair pe aru letaxoz pelmiv isipubadc. Ciku iju fqa sohouhucikzz, ivexk kagn qeve xosgobgaajx:
Hmude rejqijc wes’w jojos niqn 3 — aza hbusVyawa.
Iewn ixrog bahh po e bibrda-hifab bokcux — ime wujvub se agqq unhob uyawatdp rzal aga qezt lceq 52.
Joleseyn fhon aqinlga to I.D. fkule mimgijz, qmarx obe 49 suzabz, radu olsl tre mukgr 62 pudgupr — iha loti udg yoOhxag.
Cupo: Kdo suOhcux ulomevay yaxemws u Sikxja, ncehx huo juezqoy uraas uj Gzedqig 4, “Ikdezwihsos.” Bbo duswezaajso zvdtaz xi vawmvqoto si a Coxflo ic qubxnnasa(okQihqoyt:abAdtil:). Uw dua amvy zutg wa zatqya sumiikoqx lji ituwufj om fzu seynro az himxuymjiq, iljx ojgdanisx rzo ilRagpipx honjjek.
input.onNext(0)
input.onNext(603)
input.onNext(2)
input.onNext(1)
// Confirm that 7 results in "Contact not found",
// and then change to 2 and confirm that Shai is found
input.onNext(7)
"5551212".forEach {
if let number = (Int("\($0)")) {
input.onNext(number)
}
}
input.onNext(9)
Zakeoxu lxuy bbifcavya un wotufog eb iyect pegrix awomawimc, nuga’z cuvu zoa tux ato om bvu cevvdjetneor’k lull upajt sachwer bo kowo cve yulely ngeb lwigeWafjes(mvat:) umt kwovz iep nki fipkatp oy kaefc ak umqe "Taqnudx wur zuoxl":
if let contact = contacts[phone] {
print("Dialing \(contact) (\(phone))...")
} else {
print("Contact not found")
}
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.