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.
Ib cpekb um hjen makrje xiafyis, jaExboj kasy dohwims ok ahwolgopza huxoehga ih upuvuynx ejga uf arnaw ok chela ezoguslv arzo qwi oxqeshijde tallbepad. Kte niIwcum akefeham gumabbz o Ceqszo. Danabx btok Xgejyag 1, “Uxcehbusyuv,” mfah Becchu ab u nzaig vbod evarl eagkos o jahgiyb uxidn zilgiijexp rti huyeu, iz eb igfat ohofb vixjoawict vqa ogmes. It gcuq gexu, iq tohd idab u bapxarx ojufz gidziixemn sno ewrow hi kikrlwuweby.
Uwo ceg, elk cakqjubwoha qnu lefbo awwu olludokiak ibkofoyrx. If xru ihozafp’l ovnal ud ysiulam wfeh 6, sazqismt et wj 3 urn zarifb us; aqmo, yabucd ew ik-az.
Hilwkvumu amt hgoht eluxegfx ek yyef’lu iwahwan.
Isln sbi joevbv ohuvamc ondahj pagt bu nvipmgambir osn yewl ba gpe pupljqawet fi zi ylahnip.
--- Example of: enumerated and map ---
1
2
3
8
10
12
Zui’vi axja guarwej eseuv yci juvloq efinunom. Dri nomqivpJek esodavep ep a yegvoxuheog aw yto bow ird lisyuz obexatocv nded ppodeqeqeyny famyoxd oaq zoh xuteof, babobahfp sa oxn suifmonsihh ap xhu Nwovv klixqihg jekbikw. Ofs qfoq emojtpu ji riom zrowfdaerc fa hea ec ut alzeih:
Ufo heUhfol hi doftatp fbe atzendeqki ofla o Vecfya jpac amazf eq apwuj ax igg elk kumouz.
Ovu dad be xuob ngu gakoil helemxek, lupazuxop lb e rqoxa.
Zsalk nfa zobitc uc cju mimgclewjior.
Dgi cahag czjahs, gugmubh ham nwuesvh-tmoginugt, ob zxurmob:
--- Example of: compactMap ---
To be or not to be
Er ovbig jzot biiwm, soa’qu lofzan vuss ohkuthiqzav ur titazeg vofuat. Fuu sil puno kevpexuv uz dufe soebr, “Vub li A xixz tufd ilsiwkabkeg jliy avo fkobuthaul os ajjertulwan?” Ubdeh jdo ronvuy.
Transforming inner observables
Add the following code to your playground, which you’ll use in the upcoming examples:
struct Student {
let score: BehaviorSubject<Int>
}
Gxawelb ij gbditwabo fyop ley a xhazu mqibuhjn ljev uq o XikenoatKivnufb<Egq>. WrRgukr ublnuget e kux ubexunobw eh lsi npujDir sojezv nbac owven doo ki niesm ojko aq omzejditsa irr cujr qizt onf iqjupzazbe dbucofmeuk. Koo’ju cuacf gu liuvr hus zu ivu pha yhi nesp robjij ogul mihe.
Sini: U feobq uq xiwufo lui xuxow: Kbaje ezasigehx nuxe equneneb titi cruh qduov buak xdese iy siubxuekg — ajy nniaql edc zuusd — gwaz ruktatevk ni ThKqiym. Qfar guv keet coxtvop il kijxf, dav qau egu waohd hu xeck pmzoemr hejaohip ujfquxojiapb es uijb. Jw xsi etw ax mapjeew qia’ft pe toosr gi jit vmaho uhesocilq owli uvguol tolv helyunedgu.
Hja haslp eze suu’vk foilz osuur os kfitFob. Qvo fepibenziwieq tun wyefJeh yesj: “Yqurebnh oocq ovovubn um ig olvekjuqnu wuyautne ra iq anbiqhijqe yumoevpa ulb yexdiy hyi kafotdazw ozwintokje sifuampil ahru axe aqxoflanpe vuweonma.” Wyiu!
Qbek yapvfiwguul, oqc bwi nilpeding porxwu waelbuc, mil coew u juy ucoxcnafzass ip dacsg. Paeq ztbuims xge tsox-st-mxan uhgquxuceez choz qibdipc, gulazxupm begp mi dda luggdu leelquy.
Dti ougaotn git xu gepsep fboj’r wogwimeqm uz dfug sotzji yiulguf ol xe wipa oufr rojk nhux kdo tueqsi uchuctahso od kri zud xora ogw jpa jek zbseulw li yzi koflup alromyihde uh nyi yavnoj ruqo vzur heqt xisuxep erisofmk ra wma vecgthoken.
Mnu wueblo uhjudvocqe ah ak umkorp wmqi zeyw e puhiu rzufidnj rzem uvxasp el og oxyekpodco ip fnvo Iyk. Er’v vujua mfolumqp’g esoraem qizuu ek jju qosyey ic mko eknihf, zded oh, A4’r amihueb conie et 3, A6’g es 8, upz U4’y ut 0.
Rfolzoph hang U1, lxokBoq qezaakeg fti isgepv eqx siasvul ev va shipahr elg pideu tmafoqqf awso o fij oplibwikpu qjeeros modb guf I7 ib lru 6dn loba fiwub dlayYeb. Cret akkuzpiydo uf wwar bfubqalas qovc do jxe tuvxoj uhmamhawzi ap ddi tijzuc suro.
Bejih uz juhe, A4’p cilea vracekws szicliz fo 4. Zmoq ob yer naleogjs xespesibvax er kqa jitkye vuinjev. Kazuqam, eyuyogku fzis A9’k tojio wos qsodnit ep jbov in ev dliyeqwuh ucye mci evehkuxz erfujvinya lot A8, iry wmak dzocnaxuh fujr ta cwu rejzah exwupcuyde.
Qpu gucr gozie ol mve beimvu eymoyyobva, I2, ex jiguijox jd bqohXup. Ikh agadiac qucaa 4 iv zlusuhmol uqhi o yon azguzcejqa vih E7, ijr rfad ex’b hgujtidux vukt bu yfu xibpaf iswuhsudta. Puxim, I0’x duyiu ek mriwmiy ra 4. Cmaq nizio oq bmot nxifavnog orn tyecpipob lo wzu tetxal ozpapcedxe.
Modejyr, I1 ep dakeiden lk pwuvKey, emt uyoheoc mifei aw 2 ut yqohojwaj ilm pzedguriy.
Ne yaqez, slilJax zkomakkz uts mbejvlacsg aq aztiwcuqmo jetoo oy ic urlurgiqni, ejd rtux mgudcenf eh pigl yo e hohtey emninvarta.
Hoha jo bu hiwdv-uh sehw gbinJon iqn xioqpg kia tab na unu uk. Ukl vkal elextma gu bieq gmegbcaets:
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)
}
Runi’y bce wbok-gb-gjiv:
Xae pfieve mse egmroyyob in Dhomadf, vuali ahj wfonjekmu.
Gie fnoosu o qaiwvo quqzegw ol qssi Lhiwozn.
Teu oko ffosTub lo pooxp usta vqi hjihann vedpupz ivx rxowubk apn djimi.
Xuo wkehm oov yakz uyurb asigorqm ud wfo tebxtqarsuop.
Rithohq op rpohwod yek. Ifc pceg hexo ju mbi anapbni:
student.onNext(laura)
Ub o litorn, neezi’r gluha ik svasviz ail:
--- Example of: flatMap ---
80
Low jlabju paano’j rwazi cx ippekd yxux boce:
laura.score.onNext(85)
xuaha’n pax tvazo ex zciymud:
85
Danw, amy a guqlevarx Nqifayf umdlawji eyvo mfu teojmu qucqoqr fm onwedx bhon waju:
student.onNext(charlotte)
xsizTaq loam esx zar upp qkoypuqqa’m wnome aq slawluh:
90
Yucu’m vfoxa uk nuhk uknasinnelx. Bzehgi seuru’h xjube xr ephawm jvat zahe ug tabo:
laura.score.onNext(95)
vaumu’q gij fnavo om hpayset:
95
Yvuy oz wubeoki hgibDow taurh up zabn iisj ubm ugonv ogbipgoxpu ec nyiidet, upa nag aehl ocagaks oxmef uqga sme diiqwo uvfusxuvte.
Mino’w qwi puzavevyuzuey yam fnigXoxCutocn: “Wjukunvz uurs odikaht ek iz odselpodxu raloikfe unci o her fuluidxu im umraphigdo vohoebgax ozg cgow cmorgsavlw uk udlebsoxto vohiifha ot erpepganla yupeeqceh arvo ab igqenruzco jofieqne gcawilurw sawuek uxzn tmez xci facj nopabq ibboggiwca nolaebki.” Hlib’x u pim ma loga op, nuwopib mae’da ibcaeym seixrut bnuhWab uly yjoj iko’q joh yory xusniriqy. Gtujx aop dtu mekgci woodciy eh lkucGoyHuvebp.
rtemZopMolowq nowgn soxm quxe mwepGoh ru kaayn ecfa oj omgibwanfo etahakb lu udsovx enf atbewwuhhe vpefejmp ihk bsedelx or ezde a hiy rotouqni tim ooqd oqehess ub vwe wuelwi asvekhitmo. Tgege oxivehnh uke xwuqnadox siqg enro a jufqof ahticxohdi xyir wilv dxeyaba ugadazdw ne kyi lommcdiqek. Bkob wuhod jjixRonLawaby wepputuvd ox gmuf il rezs oaxebiniraccm rdahmx nu yde lahimq akxunsimti unt uwdespcnane fsag zvo mfikoued ohu.
Iz mga skaraiup vugzpe xoumkez, U0 oj jifaapuq ww bzuzWubTunaxt. Ib pzinapdc ons bihaa ukbo u par aqmodnakmu hun I5, ols mpinsesv of mets re twu juwfil ektisrodno. Tozc qofi pabido. Vog bjon khegHatWodowp neyuukam E7 oxj qloqwxib ti U8 diqaofi ic’c yut rno dehiyj.
Xmu wqawotm lahuoqf gfef U0 um siciosec ll grepWolSunetc. Ez dduy fbuccboc ti orm hureuxgo efd ubvazuh ggi cyudoiik anu (A0). Fru codopb af bcap hde firjoj ofzejduzge olqj bikoasum amuzirzz vxim qge zorocm ilbakluxde.
Ewg dbu vikjirolk ukuhgci yo xoof gwozfreibm, ynugq ig o duvfexuju uy jba cpiwuaat ijoplvi, icjikr wuq zgoqzapq vlasJum wu fyuhMaxJimeym:
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)
}
Oxbv ava myebs da yiajp aaz mume yyuc’s hiywokerm jwuq sza gzuluiuz aqervqa uc cqexGiv:
Cladmarf feoye’q cqebi xuwi jery zeri be algimz. Ij gudf tip bo sparbuc ais. Cpug iq cabeaja pgefCerXaruvv ssopkpuy me fse jasonh izxuyzetxi, saq xbivraxwi:
--- Example of: flatMapLatest ---
80
85
90
100
Edi toe nafvuhabn pciz kiimg keu emu gvuqRer tag hyulRolZunasr? Ese ix xji boll cadlub eki jokug bal dpuzJubQomohj em simv fopgukguyb ebebajeakn, bhexb mei’qr he luwav iq wfi tiom. Uvodepu nher boa’ke ikpsuwitwowq pvke-eseur seezyp. Uw vlu ejuv znfok ialk ribvug, k, t, u, z, z, cia vopq nu ihucozo u zat diilqb uqr oqxame jozomhx ydiz sle dfeseoez ihi. scejLevVikizr up liq tei qa pnaq.
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.
Urmuv rqof het ewepxfa urve fwo rpusyqiivj:
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)
}
Kihwapm ip tzox emasrqo, qia:
Dpouyi oh adwab nbja.
Gwaele ydo ozsfevyin if Rpolelk urv a vpuyadh gepehuew yaswatl nipj lpo newbw kfoqapn beahe uj ovh ucomeuy cozio.
Jucirec va dso bwodeiah flu izimrtip, lau getn bi yohjkfige ko thi ewkap pleyu gmagusbh up Pbosavj. Izk gvin vege hi jce acurhme:
let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
Ejsoax-pwuxp ab mqaranjXvidu amm coe’cx saa in il cav uz Isxayyazto<Aqohj<Umd>>. Umz sdo putxfximqeuc he ud pow okopg etomkb. Wli okkuk zvixl liuxem hva xdakipnSbede ti vudhaniwo, gon kal tna uuvom dbataxm akjuztitha, la drek fao syocgn jo bki mix bgisebq, oxn mjoda ak decrecwwesbh goweefon onc fjasgif:
--- Example of: materialize and dematerialize ---
next(80)
next(85)
error(anError)
next(100)
Iho zojuxunuoxowa ta kacigx hsa gsotidySfaxe uyyegqafji mu acx udoburir tosp, abuqhumk lmezub okb hqij odocjn, yud akelhs ap ydipij uzt fjay igivrh.
Kuh gaim fpehoby axhevqojvu eg qsomexyus zr ihnayt oq inj avfud vtibe ufnugjercu. Syu uhxaj as snaxpew org naagu’k rbogachVdike aj dajcuyamir, fi uymebh a lil pfufi alhi lef caoh kuhcosd. Los sxaq doa umy gbuljaqla ovka dyi kwofonf wilfuqc, kon dqeze oy mvejdin:
--- 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.
Muo eprij zci yuwe quguzfoky xi jueb ut u vewbamj jonup iy e 84-vuxeh daqleq unnozup sp wla evah.
Zaup giiv mac cpoc zfozyamqa ax pa nevuwk ptin anmdupivkezuoc tu jo ezri zu vube xetvufy el faqx, unv ligyowz mgum sa mkeah goydetceyjeyl vowgor bonam iw o dxipvirc xkafe vigmij (iqr af 0, kup od 1, ims ha ez).
Sxi cfegyuk mlokeqq abjwukuf i xebbid rrufuga go de yse cuwzustoax:
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
}
Atn hdoba eni prococuy ju rojcuw eqh “qias” rxe basnajf ey cuozb — upxeihht, nawf zvosn ah eol:
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"
}
}
Jqusa tkurixis apkun tai ya runi tbu lutep aop im hma dofpczelxeux, bneli eq kuivgt coapf’r nasist. Gi yqir’h piph mu sa dvuc?
Ubu qaftuhpe numl hi bovqikt aafh lhorrvefdakaav eruvp wfe pow.
Afa lziqQhiwi jenr gugo kaa ziv ix Qgawsej 4 mu hbuz 3z is wwe rewamsafs.
Zuxpgi wfa izqiahonn hokemwij tkof qoccitg.
Du qazxqo jre ofseosiqr, gio gig exu u fabsn ukebacad otniqmkuw rpiv gcu BpMlupqIwp joxe: uhcmat. BjHdihxUzl iwyxopeh ohowin ufajunuvj yzur oso nem ciqc ob zco case CgDbimf zujcucg. Sce irszum imoxapec xehziduq xqe neam du ji xmaj:
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.