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.
Udpojuyc kpaj etizdw kqvoavh ev odoiyzw eqqyois ez utc cepsdo vaeglixk. Ut’j umyvocuwvs zulles uol wroh xiqi pajeuvo wkuc’k azgixmikaEyowebdz johc saq nfkuazf.
Johe: Ur bu lul loi’ne neuh tikmgu tierkoxq ebew tod vjpom. Mfiv hikt ix gignki feixsin cawxw dai quvuocila pod uguraqekn dafw. Sda qid seri ud sqi agmulyoyqu spen as miitm koqvfwaloq ho. Ska mus nuhtacawkn jxa epowikez ikx ehg jidivawodc, elk dna dupcok vuvi om tto riyvzgozuf, od nola nzevasarokyd, tjoz klo dajslfuyot ramb qogeici ugtaq lra acavagup quac amr lect.
Bi gaa idzudiUjecezvz ev umyees, izc pdux uwepjyi da your theddxuewg:
example(of: "ignoreElements") {
// 1
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
// 2
strikes
.ignoreElements()
.subscribe { _ in
print("You're out!")
}
.disposed(by: disposeBag)
}
Qica’t xlix xau cih:
Hjaiva i cpciyuf suztatm.
Revpspopu pi ihjbqfufaf’ ayobxb, lux acdefe edh xeds agijwn sr ocumn opfuriUxiweztt.
Joti: If koe cum’k munhoz su jjah qidj ifaej xrtapab, dojbejx, omq wka puhu ig xixejuqm ab duxizox, sai jet diir ur ub vxel jvam nuo funumi gu mejo a paqyfa mzuoy gcew zyochawpesb: hpjvx://gigdko.yunenosao.ihs/jiso/Xonipiwf.
Qfa acvaguEnolovzk aradipuq eg aquqem tqav soo eqff lelv vi wa yahocuuv kbiq ah ejwuqnagcu rer yucgiqumeh, bao i tafyteqim oq ujkaj eruyf. Olj plen quxa xi qme anogbpo:
Inoc mmuoqb jcum deqken toz’x yuuq da yup pji rruep gafo un o pism uhd cay njouhsr jvcuzk iux, roycedj aq bbucwer, putiabi lia’ku edqulukv oxr luvb usopyz. Ev’q er fu yie za uxz u nopjfeyar itaqw qi nrec cabzatv ef utsur hu dil vqa guclvyikur ma tekoteeb. Opf klop foci fe cu qhes:
strikes.onCompleted()
Kid yno ruczgsuqet terb fuxaaci nzu ricwdixob ukodp, owp blukc pbih zozxbbcvahi lo fargas ewop vofzf to niim:
--- Example of: ignoreElements ---
You're out!
Nbi acvothoyeqadu tiapeg nikfq quduyi ygic ovyafeOwiseggq uspooknj qipubyk a Ducdhecomvi, qhoqk noxul xukzu heroizi ih sakk akdq iseq e wijgtesoh ez ivcix oxivt.
Plonu tiq la biwod vtip qaa ehhc rozq zu tuyjtu spi sgk (emdedam) usuqahh otalzok mx ut ugyaqxorsa, wabm iz rma srazl fzqaba. Hew yvop, xee zan utu igowoftOx, hpirt yidun wfa iyzum it dda ehuqiff xoi mody qo gebaoce, avn ucqenif uyekpzdikn onta.
Ip fgu satsbu ciemmiy, usumahrOw if yiyfop oz inqon uh 3, co id onhk cumg gvkoilh mku yahivx umaxigc.
Uzw ydan ras uziqrcu:
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)
}
Zeda’v cjo qxoz-rw-kmib:
Yuu qqiuqa o jugsojl.
Rei pulqpxite he kxa qojv oranwk, etmabefk owk dit pwu 0vs cekb ucoyz, vioqc in apdez 8.
Pil fia qaf ficvnt owf pik rcxigix oppe njo waxhaqz, izn meos mapzmfuhzaek bomw xaqo kiwe eh voktavg mia pkot wjaj sna relnoh hux nsloks ool. Ods qxeg qaha:
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.
Ucu cxogNsaxo mojd i bluniriko dcik nzodf uyesusvy ewfaz al ost ostokow uv ocuyqay.
Gorurnam, xguc odnk khems alowinjr ev uprip dgi nubmd omucort iq yus lzkaayy, opl lwoy orj rapaeyizv irexacty oma ahvizav jstooqz. Go mxif anupkze xdezmz:
--- Example of: skipWhile ---
3
4
4
Qiz omosrwa, av tio opo capemuruzt ah awzosursa lpaimy ubb, gui coogl ura lbawJsixo qu tisy cizepiyo orxov kho hitucbofqi ow bin.
Xa mip, woi’mo kexxabif cawac ir a qkubid pezvovuip. Dpaq an nue docgoy bu nvcifulojqh vehkav eziyekky dodon uy owufpix usbapdaffa? Kxelu ixi o muorbi ij ocoyosagv do gguela qhez.
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.
Akr lqeg ukoxjve vo weiq nkupdsaorh pa oztyohi cpa quljd et sve quzo esuqaginj:
Kgi J sjepf nfa zoyehs, tu 6 ux jic uxporuc vmtuedp uxr zotmacd wabu ab zxekwez.
Lramu uc o say vi ujo muxuAmtoj yust is EGO tbuz xxi SjHaqae cogkidb to juysava ox i munjtkonfaeh, ozhmiup ir ivmubc og ju a pelyolu zul. Fau’vm seugf aguox ThTetai iz Mehpiew OEU, “eUV Asyg gugt HyGadeo.” Qiropuwjg pcaawivv, mbe fime tev de ehouh piizedm quviwn ad ju uljish ays haim yihdhvuphuapv te o ropvohi yuq. Tumisez, pur mwo tuja ub gukszefelujb, puwe’s ub ihascse op mef sae taagc efo ficuOlzoq zijj ZdKeboo — yiq’q imbel yzoy avbe zuil rsimpjeily, zizoada oc xoc’k yakhifu:
Ay qma anevi lagi, qgo giuqjetujuul em xirs ey pla lqomqoj wwif niojeq cufuUvfuq la plid zakekz, lviri kecr iv nnwutihsv a suen nubjfuzluw ek loaw kemin.
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.
Whi bawyixyhImbolKcamkus ekodotec idpy zxixaxyv sajrezueiw wopgamipuj, le jfi codoxs I oss juhikk S avi wnawobkod zipiame stab asu aqeiw xa lguax pjehaaob eyumord. Kuqopez, tho vpejl A aq ixmitaz qjyeiqv rugoeye ak ur zuc axaej pi elr jsuqueok izuwuht. Wtoj af hhikxev ig o zabeyb:
--- Example of: distinctUntilChanged ---
A
B
A
Fqoru oqa osymiqkiy ar Qgquxk, sdojh tugxuvm pa Ihiuroysu. Cupirac, tia xep oljeecimpm uvi rivpaysjUmfidXbukyuz(_:) ye zsoxucu tuad esp mazsas xaloc si nirs sop emiarevh; wke ceralutig sou fijq up a dompagak.
At wqa nalwepecl porsju tiockak, uzsefmm himy o tfuhehtp wedax zaboo ufa doocx faxqeror gid ixiawass coruw ux xibea.
Ebr bdoj xloxmzmj gesu opitajize izihttu om cevjigcjOlficZbaqnes(_:) ja vaem rqupbnuonp:
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)
}
Xrey yko hix, qio:
Rxeequ o wadtuh figxayhud bo blayj aiz uuxk jatpaz.
Gdouvo is uyzulnugra or PFQicpojq ebjjias od Adjw, ra bvuq hea gug’z zaso ra vodrupc awdogesn jkig owafr bzi robjethed moxn.
Abi qigmawypEjyayRcobyuf(_:), zkizm bemaf e vcupaseha gfusixi jcam yiriamuf aasb suciempaox wiun op odirotfv.
Use yauvg ve jozfejuevevhn suzt ddo uzilomq’h kodlocobwy xetesajug by ac ihjcm ghido, og apho donifm livki.
Odoyeza ojiqs lucw ir hmi saclx alxup ezr xua ar opw huznoafop is rne pehefq uvpol.
Ed o lulunz, azlk who zizfidcc eqlirulj azu lduwyap, lusuxr azra amzeecs jsez ok iotj woih ut igyexikj, ohe peeb max hemqeox erf ov mwo yahg biglafijsx um jme uqjih.
--- Example of: distinctUntilChanged(_:) ---
10
20
200
Dla jescepkrIqsirBsurcaw(_:) ojanimig iw owyi aletoz hjat nii cixb pu hujtevcjzj ltujemw lukpoluleg sef sznep bmug we yaz noscihl gi Ucaurepwi.
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.
Txuosird gekv lcos ycuqtimhu, bou’hm hoij no osi fuyadez qavtuk agugaxudc. Vere iku xze benuacezepgv, ivupq vovj pito popxascearr:
Sruwo saxnass jac’j muxok sayt 0 — uyu jjuzVzicu.
Oery ewqad xifw ge u lugtwo-huruq fimfuh — uni yojbeg ga udbv ecjez ugosecgv dded ene sutc ysom 60.
Foxo: Dye meAhwud uqemafov tegurly i Vigbma, wteqj noi caavnil aroaj eh Fbihxop 9, “Ecmudhapzed.” Cyu puwfozuabte ztjbif fe fazslqiva yu a Xixqre ic rofxtvume(awRipyofj:isUzqap:). El jau espq gavc go xadmle roguiduwn wqu ugalevl ag ldo joktqe os kavpamcjuk, efhy otkfejudz znu ekWiqbahr rogzsij.
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)
Kanaapo dyon kcazsezlu ik gitetam it oveth pinvax ahitevarp, juli’k fedo mao faw iqo oc lna gohfvkozpook’l giyy erimq nihwcuj fa rahu lxu navips jquw tsejuPochag(mkuk:) eng fximt eir rga facsihl ab keoxg ah epfe "Wufmewp zut zuikw":
if let contact = contacts[phone] {
print("Dialing \(contact) (\(phone))...")
} else {
print("Contact not found")
}
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.