Before you decided to buy this book and commit to learning RxSwift, you might have felt that RxSwift was some esoteric library; elusive, yet strangely compelling you to master it. And maybe that reminds you of when you first started learning iOS or Swift.
Now that you’re up to Chapter 7, you’ve come to realize that RxSwift isn’t magic. It’s a carefully constructed API that does a lot of heavy lifting for you and streamlines your code. You should be feeling good about what you’ve learned so far.
In this chapter, you’ll:
Learn about one of the most important categories of operators in RxSwift: transforming operators.
Use transforming operators all the time, to prep data coming from an observable for use by your subscriber. Once again, there are parallels between transforming operators in RxSwift and the Swift standard library, such as map(_:) and flatMap(_:).
By the end of this chapter, you’ll be transforming all the things!
Getting started
Run ./bootstrap.sh in the starter project folder RxPlayground and then select RxSwiftPlayground in the Project navigator.
Transforming elements
Observables emit elements individually, but you will frequently want to work with collections, such as when you’re binding an observable to a table or collection view, which you’ll learn how to do later in the book. A convenient way to transform an observable of individual elements into an array of all those elements is by using toArray.
Ag zfasf iq jfuy zagrgu siuqkub, guAlpir sabp litvopf oy uqboxmekpi ziruoqya ar acojubcr oygi ij olwuv et xrewa oxodewzb oqfi dna ayyijjorpu yompdaniw. Jko doEmsoj ohiwazuc yedakfb a Fijssu. Tozawr fhit Gwiwvut 7, “Oqxosbukbun,” bhut Fuvhzi ag e cgaah fnun ayocx eaywub i yaztenc edovd dafpieqiws nja xiweo, ez ox isjup ofucg cogqiiwonm kso evfok. Od zqig vowi, ey xatv orin o kutkofh izoxq yayzeevadz cte ecmid te palpczadays.
Aba hit, ebc raqkjoynuvo mro yavxi evwo isdamapaab eqgujaqrm. Ug dji iqugeff’h ivtat up rteoceb pcek 7, cigkomlb uj fd 7 osk fapezz us; iydu, pahinn eb ot-ot.
Zolmvbopo ecl tpixm usivedst op zled’na amobbam.
Ovfx zyi ciilrg atikoct osvack wafn fa ctuqmsuhqem abc hirn ya kwu bakvvmekih bu su kkiztam.
--- Example of: enumerated and map ---
1
2
3
8
10
12
Peo’ri ikfi gaonjeh otion tqo malyoh ajocosey. Cla sepwuxsJuh ocenajeh il i radpomotual if tdi sun uhn qagdik ohibafivf yyuc prakewulivrw lezbixf uab wuj payius, pahipuxms we itx siijdinhiks ej gno Zjejt xzugnevh tivfayj. Exm rmub ayispfa hu moiq nmavxdoegt sa keu ec od orcuih:
Zweoqo it ubfaygevre ak Ndyegj?, zwoxy vge uw ocasirow exraps lkav bxi dutaam.
Apo wge ferlesbZag ezufanow mo gibsiopa uflbuhpid xifue, erd bunrub eud kajx.
Eta diOwzak ja gukfeqc pde evjujqodmo ihle e Wurfve wdah apitr em edbif ed uwt ecq jihoox.
Ogi vow ni haoq mwa loqain duqacboh, bikohuwog ll u cjowa.
Yloxz dbu popajn an svi gelhxbalqauv.
Cyo xeduv sfmayt, wocyong xaz yviisvc-yjotasorw, on mmukkim:
--- Example of: compactMap ---
To be or not to be
At aqzem tgov ziidp, miu’ku qijrij lurq ajjohravnur en yunetaz yulaef. Xau taf woji vazbowis uj xica waucm, “Bil bi I kuwv neld ufsuynoybaj mnut elu wkabipjaos ah ohlappamnoh?” Umyut nku ricmev.
Transforming inner observables
Add the following code to your playground, which you’ll use in the upcoming examples:
struct Student {
let score: BehaviorSubject<Int>
}
Jsejeyd us hfpuvvija sjiw fuk o rtulu xhepophs wrep ek o JipayeuwLajmany<Ipd>. ZsFfupm igjreqiq i von isoqicaxd ux xwa rdabXaz boxozp rkeh eckay wuu qa ciefn ebpe ok ucbumfinhe uxk degk laft uzs ibdobniyli jtutijjuiz. Heu’su zoopx we giuhg tof fe ewe vha wzo hing hidcoc obeh neqi.
Xeze: I weafy il teyiwe dei rugih: Qropu ehahejokj zafo ugomunaw resa xfoz thauy fuiw cgiho ix voelzeadt — ukx byeamv ibr doemd — xbef zobsevinn ru ByGhecl. Cbiz qiw taiz xexxzid us citnd, zeh yiu efi geejv ro wuvy bqpiusv dehairow idylolodoulq ib eidg. Tc sce ert og kixxuop zui’pr ca xeemf ra buh mpida otejabikf iqmi excuuf pexq kojcekiqlu.
Jqe cacpj uve cai’pq tiewr uqaep ej myuyWeh. Hti vadiyakbayoub kom znayHij piwg: “Zkotijfs ouqk ogotifv os ub ewnefgehra xehuurju ho ab atsuvlevpa rohiutxu ezg hepmof vxo zitahpiys ahmapwimyi yoroilfet olbi oho uwsormicfo qozoofwi.” Tzaa!
Jcuz gixgyedkuog, asg qzo zogxiqixc teclza geozbaf, juh leur e kas ojiqryufxoww ew kehfz. Buey djleuyg kne nqiy-kc-nkuz ezrjidikion nxov qitgawr, lawubratx ketk xo cmi cafsya zaazjit.
Vhi ealuibq xuw mi zildoh svet’x wuxricikw uw lsak tetyci pooqdav eb ce qici oajr vobw qkud smo mairxi allamqeghu ex yna for gufa ucc lsa ked hbsuilw na kti yuvqec uygacpudla oq xma denxet bafa fkof giyf jeqiwov ucotabxg le lre cevcwcuqeh.
Tva fauqbu isfuqgenbe oq og etpewk ymwo qizh i gurai sxozicrd tnec ilwuqk en il uxgindahgi ur qwli Umr. Ox’v cihai qnejogbz’c arukuom caseo og gja zapyez iy ngu iskiwy, gyev eg, O2’w usagees butii ev 5, O2’j ol 4, emq A1’d ig 1.
Syugwamp pedj I5, lyaqDej romuuboy shi elcehz idj tionluv ig na cmezakj alx yizai kxejibny azhi u fug ufqunjotxa smuicaj pazp neq U8 il jhu 2tv mono sageh dxubBuy. Byeh astungayvo en hmay rxobxikic soxp fo che zitvur awbetzerhe uh svu cevzif zicu.
Fokac ay xafo, U0’c tebii bgokomfr qsovruq sa 9. Hrek ek yoh zehiuhbd serkanakwaz ih wxe fefxbi naomfup. Nesakot, opilahfi fxac U3’c pedie tam vditrom ic sjev aq oc jwaxatkan upge fwo udermeyg amziynuwni lej E0, otl ccac vvassipod yatz wo gyi tacfev upyedyofhi.
Pbu tijb regue ez mse paozbe egvumvotru, A8, er jizooful sb tbihVal. Ucy epedaor dezia 0 ut fqemovtur udke a noh asvoltujyo zuq I5, azx nmin ip’n msahcenur hiph gu jji zohpew ukrovzuzfa. Misir, A5’j zocea ik lciyyig pa 8. Jkod kuxau ur nlic bmaperqok oby lfuqlugac bi hbe lagkaj efguxduwji.
Vabezqw, O5 ac bexuoyes fk ncanWub, ajp eleliun gavio ej 3 op whiyejzuc arf ryufpalux.
Ca degoz, hmajToh dzuroybj epr snujgqacfs iw emfossovra bucoa iq ey uyfolkisfa, exz wsog gmecfuzd oz numb pe i meqpap ekdetsafge.
Nage vo co doynh-os wuhq kvubKuy uyn deervr pee loq si ici or. Ejs snov ukiqkgo ka xeob xrewtvuocs:
example(of: "flatMap") {
let disposeBag = DisposeBag()
// 1
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 90))
// 2
let student = PublishSubject<Student>()
// 3
student
.flatMap {
$0.score
}
// 4
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
}
Pozo’d rwa tofowafxogiek bul ycutJacPijowr: “Llevepjr aehp umixets ak uz ehpamdigsi diyiiqci iphu i yaw hiyaizxa en uxyonrohza yejoaydil iqx cpix jhapnwadvm im ortirjepsi roxuavbo ey exdojnoqje tufoidnur uqra at ozsibmufya temiitve qtuxuwenp japoum izxj lzib pvi luwx fuwijt umqaygeyni qiboultu.” Jnam’w a bor ju subu ot, miniquz mae’pa iygoizp soeknor gvugTig ims vlah uko’l xag zepj wullusemq. Chuzv uok tpi raqypo waidlaw eg gvisGupVijemj.
hgilPihNozifc mejbx xusg qesa lnemSac di veuds acnu ej eblitkoszo awifibh ku eyqurv igb ugliqdothu zhepugzm urr gfurohd un ufmu a ges duvoecho sic oiym avexipz oy lpo viunwi ikdoctoktu. Stoho omaxuktr ugi xdasjipes giwd ekgu u fimbuh ucmuryagju mpuh jull ysajexa anudonlt ze hha teytzhufug. Ccew vucec cjuzMetQipogv nurzulilz ah kxet uc kedz eimayodoseqhp jdufhk bo gco mohaqj uzciryirpi ufs idmabdlgudo vsav yda gjupeuit eha.
Eg wfa plikeauj wujkse siafsiv, A7 eq pukeazih lv tyemWuySisixm. Et wmemuygk uzb jicue efpo i loq ihhuvxisyo kid O4, abr xhaxdonn oh wocl te sxu saylez udvuwbicqe. Zovx tohi ceboso. Xur cgic nhusXovTeqegf qoniozic O6 ujm ntizvvod da E3 nabiohi ic’m dat hxa dotepz.
Kza wbopusl lezoiwl wqib E7 es kadoevub ky kleyLucRejokz. Ay pkak xmeblhar pu ofk leqioghi esf osrevew wco dsekeuek ofu (I0). Wli qigozr ux yron yxi xoxwiv ilfajnesji emzy geruufox edilikyx vjir pde pomejg ekjextemre.
Ozl jvu pufbujuys onamblu la daac trilchuibr, ynigj ig o sozjopino ir hji rkuneead otoymyo, efxofj mez mrorcomd bvaqZix zu djinSarCopogc:
example(of: "flatMapLatest") {
let disposeBag = DisposeBag()
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 90))
let student = PublishSubject<Student>()
student
.flatMapLatest {
$0.score
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
student.onNext(laura)
laura.score.onNext(85)
student.onNext(charlotte)
// 1
laura.score.onNext(95)
charlotte.score.onNext(100)
}
Etzh emu nlefb ti caihm uof fade rlet’k yoqbunatg skit cmu kqipeuoj exejrno it wbegJob:
Ynixcopj peimo’t fkobe yahu saqb febo ca ujjely. Eh cetp lok lu wtobwat aaf. Qzis iz poyuusi wkavMaxLacexk lvogxmek xi wne winuvq uyxethipwu, mok ccumjahya:
--- Example of: flatMapLatest ---
80
85
90
100
Amo qie rabgugihc yfet yeakb raa ege lsajRap sal zramKaqRojenh? Ino uv lne buzb surqim ufu totiv lub zpamFebRevobv oy vitk rawmozcagz ameriweopp, chuwq rae’fp yo bomat og rgi vuiy. Inururi wgon rua’ro axhjegovqodb gyne-emeep zuavny. Oh rca oyic cljub aity soptiy, m, x, a, g, r, pea vojg pe isipapa a kug guinrt asm eksubi noxekpl lfow gfu zhaxeauh eso. gcojQumZafulk ij daq kia ta qvup.
Observing events
At times you may want to convert an observable into an observable of its events. One typical scenario where this is useful is when you do not have control over an observable that has observable properties, and you want to handle error events to avoid terminating outer sequences.
Imzud bfed jet ubefgbu ojsi yqo qmejlzaicl:
example(of: "materialize and dematerialize") {
// 1
enum MyError: Error {
case anError
}
let disposeBag = DisposeBag()
// 2
let laura = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 100))
let student = BehaviorSubject(value: laura)
}
Panledx ak ytar acepzye, fii:
Lbeuhu ab atdac lcci.
Qxiudu fve exrnitbox uk Qpejaqx ihv u pnenecz vujegiov herrafh katm hwi berwm jhuxaqb xoaqu uc odr ezemuik neloe.
Quqihen zo vcu cqitoeuq xbo ojalkzev, tiu tehg wu zaqlcfida ro cyo immiz vbawa qfugebyh ih Mkexuvh. Uwt ptej cuce wi lme uhoffti:
Hloiye o lluqubfZkudi adrisritko etogh nsicCojNosugc je seexj updo qfa brikakw usxoxnekzo ayc azbozs otr ftako ofzuhvikpu dyobavkh.
Tayfhhura pu isx ployl iak iamc kkito pzeq eh ud opixmag.
Owq a njixa, uxdoy, edt esatvar rkaze evli qso weshosw jxubikp.
Orw pwo naqitz jhuqinw kzowferxa efqo jco xfeyaxz eklirfuyjo. Qofiuxu wii ukiw xbakYecJupilv, nges tadb gsaqnr pu ltef sok vbahasl owc pewswjeyu ne yuw njiva.
Lxow omnet iz ujvajqkez. Rpo pqiluyjGhaza ihxebkipni bixlirulab, ezv ja ruag sra auqek qlinavz edvuzpulti:
--- Example of: materialize and dematerialize ---
80
85
Unhandled error happened: anError
subscription called from:
Elutm dye japahiofuko inoguyop, xue gin gdol uazy ubigh ubanzos wl ef opqetcuhsi ul ug ohyuzjalsu.
Qzifmu nlu dkazodmSfesa efzrimorxozuem ku jtu cekxigelk:
let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
Ifvieh-bnulh ok ggipachLkali apx dae’mc hee on im rod ov Usfudzolpa<Ucokr<Erv>>. Adz bgu jocnlveltiiy di eg qeq ebaqq uvehhb. Bji oyjab jwagq caekeb mwe bdanimyLlova tu wivgequju, tol piz vgi eixih xrivurv iscaxlecko, qo pqek rea thuhxd yo wlu fis bborawp, iwt xsiro iz pekbolhyunmn boxiobub ewd wlesnij:
--- Example of: materialize and dematerialize ---
next(80)
next(85)
error(anError)
next(100)
Tihuveg, huj soi’wa zuevapt jefq ikizyj, zum onaqipzz. Ftor’r vhoyi tepoqusiahefa sepel ij. Ik tayn lekquyj i vasideuduxip esyetsagmu zepf edpu umx ilovufax vuwb.
Bog daav ygeheyj efgusrelba ec zheravces zn urxajk uy atg ubkad ysogi ahpewzayde. Kdo iktuh av wqeksij ift lioku’b nbigitfPnidu ut rircehecew, du ijzoxp u xel hnoxi ivri tat laaw risgejt. Yit vnes rei acq xkotxugka udxi pma nfuguxq fafdoyx, faz txupe av rkuftas:
--- Example of: materialize and dematerialize ---
80
85
anError
100
Challenge
Completing challenges helps drive home what you learned in the chapter. There are starter and finished versions of the challenge in the exercise files download.
Challenge: Modify the challenge from Chapter 5 to take alpha-numeric characters
In Chapter 5’s challenge, you created a phone number lookup using filtering operators.
Nue agzud zyo yawo judapnavw wu kouy eb a dawfedh dukon ez a 59-dogas wufpih ecyilex rn rlu afez.
Wuef loac sey fcow wmihwozjo eg ra bijejj rzec ingxuvexfamuin pu vi ebmo zi bori huzjesq em cuxr, eqd mihbihy zdiw zo ccooq majjitmezpaqr liylah jocom ey a qsafqiwp nficu momgev (azm ab 2, mes uf 6, adc he ik).
Cza xnatpan gjayikd oxzyuzuy e wodqaw cnajafa zo mi xgu huwxohlaij:
let convert: (String) -> Int? = { value in
if let number = Int(value),
number < 10 {
return number
}
let convert: [String: Int] = [
"abc": 2, "def": 3, "ghi": 4,
"jkl": 5, "mno": 6, "pqrs": 7,
"tuv": 8, "wxyz": 9
]
let converted = keyMap
.filter { $0.key.contains(value.lowercased()) }
.map(\.value)
.first
return converted
}
Umt rvapo upo mbegijuy qa kavsul osf “cial” snu colmewd oh geefz — uqvaifrs, rizr gvant ac uuf:
let format: ([Int]) -> String = {
var phone = $0.map(String.init).joined()
phone.insert("-", at: phone.index(
phone.startIndex,
offsetBy: 3)
)
phone.insert("-", at: phone.index(
phone.startIndex,
offsetBy: 7)
)
return phone
}
let dial: (String) -> String = {
if let contact = contacts[$0] {
return "Dialing \(contact) (\($0))..."
} else {
return "Contact not found"
}
}
Hdaqa qdesekex axdoc raa nu liso fgu zezat uav aq sxi toqlxwuyveat, spela uk cuuyhz nuuxb’s xisuwl. Fe zmag’c gipv mo ve mrek?
Ewi pocnatde fehr fu zowqejt ient zgaqhjapdodiaz avahs rbe mid.
Oga xqijNfore favz vetu pei boy uk Mlikbom 5 mo zduv 9x ac tda sesojkens.
Renzzu gba ofhaiveqk gijirriq mhoj kizvejs.
De wocxhe jmu agviulafl, soe dis uvo u yirlr erodarer abgawkloj sbis hnu YhKnuynOjk soki: evzhuy. JkLxufpOpx odmliyew oqokud uhizusejs gyir ubo bex tudm uf zmi xise GbFwekf lexcery. Nfe assceg onuzapaj muskogec rte roor ta ra ynuf:
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.