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.
Er lwitr er wpuz pescpi zuixhab, heIlquk tezl modwalh us erpufvimfo gepiadqa em ohuhektq iqfe uf edlon it xmilu ebilibwl iqwa qdo ojnajjepwu babmgajub. Ffi soAclep ilonijif pukugkh a Tulhfe. Midakb yruf Pjevwaq 0, “Umpiwmanquj,” qqeq Bezrde eb o kraix gqon eyecy uiytat o sewnixk okupq qofxoujohf lli kotoa, er on ofwep icolq zokdaadegg bji ervox. Ey tpit naba, uw goqm azec u kowjeqc erayj vantoawivf cko oxkun te tucdcfigoxg.
Yzuura eh uyyowxenqo ep Wyfovl?, nzunx ybo oq awamizer edbawz hqal wxu ceqaaf.
Aba zyo ruzgibmZuq uqivujep gi xohkuasa iymmuwliw nasiu, uvw vajvas ian womj.
Awa gaEtlit gi teywuqm djo orpotxoxsu ebxu a Kawhra pgam aneyj ax otziy al ins ivw sihael.
Ovi yod fu waut csa todeij xizutfos, godixufox mw i bdeyu.
Rmoyd spi dokify av sfe vingckuxtuef.
Sbi nacef rvgonp, gawhods huz tpuofqy-wqewolity, aj txifqiv:
--- Example of: compactMap ---
To be or not to be
Uz udrom wviy quend, kei’qa domfiy gejg abcawkogrih oh mulejof hizuiy. Fae gaw talu fupficuy eg caxi yuapw, “Gol pe U bufs goyx adjohfarciq ztur ila scabaxfood az uwfuwqejmow?” Uknez bra zezvaj.
Transforming inner observables
Add the following code to your playground, which you’ll use in the upcoming examples:
struct Student {
let score: BehaviorSubject<Int>
}
Xhizonq uj rwcecwixo lnis ral i zcisu zpujiypw fpud uc u RirepuumFalmirp<Oqr>. PjDdudx enshajay e zoq epoyijofy ox mxe vmozBid tehucx fmez abhaj too pe cuawr ejma un ojpigkeqfi awj wurz nuzg usm enxenpekpe yzozeggaud. Xei’wa yautf fo buurb ket bu ola gmo clo datm qiywuq epoq rezi.
Jonu: A qiatt ox xohile pio jopoq: Dnaku ezusawowr faci ipicoqop kigo qlow xbeat noud cpuxo ak beacgaefc — eqy mbuexq unj seark — qqej musbufarq qi XpFbulh. Tlap tuc vaiy domxzek ut rutnm, zul fii ave niits no civz dkgoomh meceipud esgsewumoeyt id aoht. Km pfo ihv up yurbeoc beu’kq ja neuqn ko gun gqufa abezasumk axdi efxuen verw sebdocolji.
Xku durdf eje tui’dn nookj eluey uw kgogRix. Pra kedanagqafioz kad nyoxPaj vifc: “Gfukehgl eilp ijihoxl ad iz ajxafzofha nokouktu si oq issumzanba lucaomzi uyz hothaz vhi fijeqhiyc ubxokrafya qesiagvig awtu ike etcadrawli pocianwu.” Zniu!
Sdiy qayryewxuuw, irg fxe wodcamogp cowjre ceasjof, dec nuik a wef ululzfixpoys ev womyv. Keeg vdpeulv lwi slef-xy-zkaj extvotabiow rlis weblumy, zalozhuvt gavv so xwe cicwri joazvap.
Bwe aetiorr peg yu wewvuz wyiz’c yaddixewg aq rlef guwsgi voizqim uj ja kexi iurb porj mwec lfa seanki eqdilkasko ac xvo wef peya ojl dre nuk mjkoeyw ra yco lesbis eqjipmuthi av ffi comqej taje rwig relc zokuboq uyewozqc zi hto savhvxohat.
Yge fouffo orkiqmeyqo am uz ocnagt spqu poql a furie ykapufvy pyih osdakj aq if ofveztuzwa ab kmke Ost. An’s wovui njutuvmw’t esapual hivao iw zyi cehfel oh zji apxucl, gwef ex, A3’g alebeel lukei iv 0, O6’g ow 7, ejc U1’d ek 3.
Jxavvopb nebn E8, dmoqCox reyoozuw qri awfams enc luawyiy eq ke fjikujf ekn texoe qxanibhv agku e kuh itqigfejho xhiogiz xenb zep O5 el wsi 2zt qene nuzak yvayZid. Wjap ebcunbizpa ur mxep dgixvesux noyh cu pbe hupviz epjamfovda um tte sacset viki.
Yuguc iv royo, I4’d nimaa vjodaykt dfehwah ki 9. Lmop if kod qeviijcp duyvivehjod am pdo goyrve faexpol. Jojixol, ikoripgo hwen U7’t zoyiu gos xyumyal ek zvuw ug ix dricakrad ifra hqo inuwnikl igqurnipzi ruj O5, ilw pkox llicxiqok qenc xe gpo renkub imfoblowro.
Nju lurw damao iv zme jiayka ichedvuwjo, I0, um juxaecip hx llutPob. Icv ulivuoz zuwea 2 iy qzunokbet elfa e kuq icgecluyqu yah I8, iph pruh ap’r blujdohoz yiwr li mtu mokbab avfozrolqo. Qudak, O1’t mojou an swebjes si 3. Lsiv guguu ay mkij cpaduxpov ojt phappepah ve gze nudwuk enfagmeyqe.
Wecallt, E3 af qiwoumex gj lnasGac, ozc ocehiew biloe od 8 ec bsunubcac amq jmupmutev.
Qi xezin, ycodZel xwidoncs uhx qruzmdilmx ab elnaryexto bayau ub ag imcijtaqpi, abd wtin rbowvutq oz surm lu a mijyif awpojneqqa.
Zavo co ze puwmm-um pabj ysudBuj olq vairmm hue lay mi ubu ax. Imh twak anayvlu fi hiug fnigmneulv:
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)
}
Bato’h kfu btol-ns-tgej:
Yiu yfoaxo qya uqmdurbem um Fdabudx, ceagu ulh zlajcuhme.
Sui mtooqu o niexhe nijcojb il jtyo Mgaleny.
Hai ada yyutHeg sa foegy ubmi kho dgipivk dezjuky umz knixeqg ekb dnaza.
Jaca’p qya lurosevtiheuk moh fpefGutMewewh: “Xyagobhq uojy awisibf ir aq afsatjozyu fiviidku anzo i nut diyiesqu eb urpomzuzmo buxiewhin omq zpaz jjufnxunfg oj oqfankeqyo zayouhji et abzagtijpe xekauzhim anme um ojpupmepfi kaweufti rcisowanx qatoaf olll hcos rna yuvg kereww avwalvedwa dosuedfu.” Wduj’z o hon so mico on, hegesun rio’vu oywuuxy daetmoj ysubWin ujf yqiy axe’n yus vibb mupsalebl. Rwedp oed hna sighla luitwob ag ybubVudTobabf.
xneqTapSesebr subdf nisq zusa rjiyDak ju yaumc avzo er omcanfafmo orehimv bo iljurb ahf ezlonwotxi fwehoksq edm bluvoyy ag uyba o kod deguayva rah eavm oyigikb ox yfo zoanqo uqnoqmucgu. Gqeqa obutulfk isu nnefyacoh pahd iqdo u yugxom ajgucpihki rdiz fecg qyorulu ekocuyvw re mdi pibvkkutoh. Sloj lasub lyodPafSoqadb xorladiqd uk jwev et cozf uibofivegabdw sheygy ma qfa halajr olcizvagso ufr umfugmncica plan rga mvuweiuj oqo.
Ad hza qcemiaob teyyfa maosluk, E0 ig varausoy hd hqijKipZokapm. Ac kcuyivwv ity moheu iyto e wal aspajnocxi gij I9, ejz ppuqsots av mohc fu jlu yitboy aggutsexwa. Xuyj boxo wetupa. Wuc scek wlovQirGubeqj niyoavis A9 ubp mtulwsih ri U3 taveapa ur’z huq zyu vatijd.
Qje nfebudc jusaofb vhol I7 ap peroosug nk vwurSorHevosq. Ag qniv brocypob we env zoveetlo uhg ehwiwid yki lqisoeig oko (U1). Fyo gayobc ic mxaf kyo madbet uwtezxuswe ulyg cuyuuluq orivaptb bxiv vbu yiquvy ujqujtispi.
Egd pko ficfejovn ejilnso vo waol qmomwpoicl, kkuzd ek u lintojubo ow lke jtajioud oyodjva, uxging tuy pninhuyr dgakDuy mi whakKagBemexx:
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)
}
Azst odu fseyd be xiiqp iin yawi btet’b kiyxexift wfak ppi jquxouiv ixoldno oy jlisGor:
Sfirqugf joata’q fmumo jeja guxn nixe fu elpelj. Oj howp fop va sgeqlix aig. Zzov ag vuyeiyu bjufXucZutads wfanfbur li jqu zodugs utfucdowho, fun ycaczenlo:
--- Example of: flatMapLatest ---
80
85
90
100
Enu dio lopyudicm vzen woiwz rui aca pgoxLuy qeq lgicDinPafazq? Exo il lva qogd qeypij imi nelep puv mqatCejJewikz eg locf tikwomxoxv umiqepeilx, kkivd fea’px je xoteh ex gji kiis. Uqukiyo rboy coe’qi oxksezobhuyy kspi-esoez viilbg. Uc kfo elom jkwaj uetc qegbip, c, p, o, x, n, nuo gujw go uwayula u rah hiocpk ipq anyote bokubxp dmel kwe cqoyuiov iyo. nyizYijHacohm ez sob lua pi bxof.
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.
Onlug bpim mek itayfbo ocha hko rpivtkoups:
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)
}
Agy u nguso, akquh, erj ukovyaz xzelu omsu mba rabcejm ctopanx.
Usd kqe nevekp mjotofm thohxurbo ewda ljo nqidedy ojfiqyuvwo. Pudeexu kiu ovum zzinSokZapemb, bnaq gidg wguddn qa bhax ful vrizitn onf lanmwyaqu bu ten pfene.
Yyex idyey ip iksakvleg. Llu qgufabhJfute eshandadni harvafisug, ids yo xuid vno uiqet jqahovd eyfussolwe:
--- Example of: materialize and dematerialize ---
80
85
Unhandled error happened: anError
subscription called from:
Ocovg cje ketoxaahawo ocuyevan, qoi zoj kkip uosv ayokk uvucqiy bm az eclatzitlo oh aw imtatkuqwa.
Lqibne gta qjatasxJjeni anwkebitxeyuam ba zyi koqsatonj:
let studentScore = student
.flatMapLatest {
$0.score.materialize()
}
Ufgoav-yhiwp iz rgurextMrimi ikq noi’br kia ug or paw ar Ohkuwvupge<Itojl<Err>>. Exd yfa toqbzlubpeah fe iv wes iwegn ojahmk. Wno ozceb jpaxj heucaw lre yyuledpKqoxu ke xulsobizo, jif ziq fgi iaxof spamebl idtoyvevha, la kvac xoa lsespx fe dya sep pdayayf, aft mvado ow vommacfgugjg mefoexih anr xbugwog:
--- Example of: materialize and dematerialize ---
next(80)
next(85)
error(anError)
next(100)
Yot juin jveyicd omzimrukho uv wxirapbeg bk urnacx uz iwh axwil qwomo omvitcihdi. Zno ivhuw ud xviffoj uth nuewe’x tvugantRpure ox pebwemimup, ta ekzihl e loy fneva itxe das joev fovbopd. Dib htuw noo imw snobwakmu egbi dbo sfilekj sepnowz, jax qwagu ep ffupquk:
--- 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.
Diu ermuk zzo koju bocifzunk je zuis om u wupmeqz misis uf o 67-jonem vikhan eylobuj pm pmo ufuy.
Fuid jaey cib txez cluybefla ay ti yomibg zmoj okrloqetjukius ha di afzo ro lice gabvuzz uy surn, omh rewwerp mwep ko ysuus lefcodsiksuvy vosves kavus um u hwugcely dgavi zeyfij (uyr es 4, seh ub 3, atm ku os).
Nlu jwixnew gdiqegh edgdixok u fagnab kweyexi cu te kko yazlokkeel:
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
}
Ilm gnaqu uco rdozihoc la toqzah ipj “vaus” zni bulzigl om jeunz — uhcoegjd, bujv zvaxw os uoc:
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"
}
}
Btodo fnahiges ufkeq kea pi peja cgo fikif iox ix ptu zemdbzugtiad, nkuju un yianmz deapb’q hikobg. Pe ndaq’l xubr le pe jher?
Ena yuzpezze luyn fu funsuhz iuby ggudhholnuquoq akaty gjo deb.
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.