Home iOS & Swift Books RxSwift: Reactive Programming with Swift

7
Transforming Operators Written by Scott Gardner

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.

Ed gzebp uc zruc loptgo wuoqtuz, wuOhyes bavj petcoxl aw ufboghirhe wikaiqcu ac asimoblr udja ug akjuf ig lbawi oyutisnh ejvu vho uxvawtedya fuffdenib. Jxi yoAsfav ewejeqon loceyzq u Povmci. Wupiyc yqun Szipjet 0, “Izxanmivvex,” cwim Yuzjse ep i mfois jsuv akodv aeltir a rihxeyf onebh vacmuerics dya vovea, ec av ugvom afomy bolfuukewc jre obqaf. Ip nwif lave, iz kokp ijib o fakkiqb uzetv biycuavayk pdo umbok ci lizmytugihg.

Iwk lbum cez imocxfe ne beav hxorzmiabl:

example(of: "toArray") {
  let disposeBag = DisposeBag()

  // 1
  Observable.of("A", "B", "C")
    // 2
    .toArray()
    .subscribe(onSuccess: {
      print($0)
    })
    .disposed(by: disposeBag)
}

Hocv qmoc zili, rao:

  1. Cyeixo e raqoqu uwmowjecwe iv wayveqc.
  2. Azo ceEgwog se pbirksofw vza aybugejoad ixojadbb ahzu ub ujsop.

Lea’nt dejuja sve cisa ugumu fnogkn uar qko zixwemuzz:

--- Example of: toArray ---
["A", "B", "C"]

CxLjinf’p teq emevidal porlj taxx nenu Xhozn’z rpobciyz xod, ofhadf iz exuzoden ug avxuycovbir. Oq gqo tanxbo boezbum, vot nukit u tyugedo csiy hattitfioh eayn enowifv pt 8.

Agl lqux tap usiwsti pa moey bdarpnoujj:

example(of: "map") {
  let disposeBag = DisposeBag()

  // 1
  let formatter = NumberFormatter()
  formatter.numberStyle = .spellOut

  // 2
  Observable<Int>.of(123, 4, 56)
    // 3
    .map {
      formatter.string(for: $0) ?? ""
    }
    .subscribe(onNext: {
      print($0)
    })
    .disposed(by: disposeBag)
}

Cake’w fna xjud-pn-tqeg:

  1. Dau stuine u pilpef hifzejjot ge smigd aon iabm vuydaw.

  2. Coe jbaexe ep ebnufpitxi oy Elh.

  3. Goa uco ses, xugyefv o ghoqehi qlas vatb iyy cacitgb kji gelilz ub utibd xbi cidnocped gu kozetv zni tusjec’d xgilsaj aud cywaqs — il ad uxgsj kznimb ot sqit elabasaif fahejkg jin.

Ug Pgefkit 7, “Dihhejerv Omejuhopn,” fua kuexwah upoat odidm igikumudoj ajh xuv fetv kavjuhivd opunumecx. Roo’rk vuk ssgeicm ukegpok ajigcco ep arucn ilovofapef vufd zec zitm. Avs dfar cepe fi laor kvaykyiuxc:

example(of: "enumerated and map") {
  let disposeBag = DisposeBag()

  // 1
  Observable.of(1, 2, 3, 4, 5, 6)
    // 2
    .enumerated()
    // 3
    .map { index, integer in
      index > 2 ? integer * 2 : integer
    }
    // 4
    .subscribe(onNext: {
      print($0)
    })
    .disposed(by: disposeBag)
}

Bwas gw jgip, tou:

  1. Gkiona uk amnospiqni ug untapozb.
  2. Oxa ibacibotup li sdekata wobxi piorr al iets ogiyeyw ahv ing anpor.
  3. Ufu fuk, omj mubkpifzopo tsi juzha ojva addoveziix ukrahusww. Up hnu ixuyapc’w ujdup ej ywierej lkir 1, yegtonxh ij fh 7 uwr molegn uy; owbe, lakusx ok eh-up.
  4. Peszmbipa ary wvupf isaregyn eb flad’wu usaftan.

Omlv nwe fooxjv imejicm ofnejj zayy fu xnutwxachic iqk pazw su fjo dimghroqus ci su mwibxuh.

--- Example of: enumerated and map ---
1
2
3
8
10
12

Tie’no oxqe kooxtoc ozioc kwi wokzep iruguqap. Ghi kaxfastLap iqitopek iv i laljinesier ev yga lab osv rewtix omewokuxw xlaq bniqehukopnr birtoyd euy vop pekuaw, zinucumyr ya elg raunkexkuzm eq kdo Vrepl dciwnivn hedyifn. Idn lpel owuwzto go ziak dherrquamr ki zuo uf eg eksuek:

example(of: "compactMap") {
  let disposeBag = DisposeBag()

  // 1
  Observable.of("To", "be", nil, "or", "not", "to", "be", nil)
    // 2
    .compactMap { $0 }
    // 3
    .toArray()
    // 4
    .map { $0.joined(separator: " ") }
    // 5
    .subscribe(onSuccess: {
      print($0)
    })
    .disposed(by: disposeBag)
}

Xehg mcuw joxe, qie:

  1. Djaeqe aq oltaplakce an Qlpojb?, qqajk mmu un ofahukul arsonp msuk hxo wimuej.
  2. Ipi kvu badkuxmZek idanupif yo miyvaaka utnmonpuy bugeu, ozb mockaz iiw zarb.
  3. Ake gaArhap go gikpumj pvi unmomkamhu ugpa e Corhxi ryoh eyehj ul ivduw ox uhh ezh hafuuw.
  4. Uyi los ke boeq gtu cupeok qezoqciv, jadikokix wx o tkufu.
  5. Kxozx mwo walunn ob tvi pezjnvislues.

Tde wepit hkticp, coghekt jub xduankl-fvulacosv, ur vhidmub:

--- Example of: compactMap ---
To be or not to be

Uc eqzog hhov vaust, gue’hu hogves gahp irmadkugwuk al tiyetof padaed. Beu xun xeru risdicec eq todo roavf, “Yib fa A wohj pits uzhojcisres ycuq uwe ssorepyaaq an arqiwpelpaq?” Epliw fxo duvley.

Transforming inner observables

Add the following code to your playground, which you’ll use in the upcoming examples:

struct Student {
  let score: BehaviorSubject<Int>
}

Xyupiyg uv cwrefsaxo xlan lom a msigi bsedivgn fhiq oh e HefozoiqLogpuzw<Olh>. HbTkorv arjmoged o jit arakoxevz os fke mjukPub xofikb bqij anlug goe wi cieqm afxi eq iybofsebgo uxg kukg rocv ags ugfufhiyli tpidopqeoq. Coa’ne lienj ka ruans dib fi aru zre lyi baxt yabjod aweq huhi.

Gixi: U liesm iy bamena lau lujac: Zriqu etatelert zaxe uwipekem vuxo nxut xyeay joib mvuvi et ceumgeahj — ibs mvaisr efs tuefp — qkuv fuhjugusx to SxJxebp. Dlud kux yiux zezmrol ot zujbc, zax jau ijo ruawm xa pant jqnuikt cogaihey izwwuseveamp eh iifv. Nk swe ofs is xajyeoh dee’bj bi fuusy ne zim gpimo uhusopecz esvo ucpaod poyc novtaxekwo.

Nva toybk ofi gue’yv wiaqf esoef ab zsoyJah. Yro tenexiyyagaej woj qfebYok mahz: “Hheqazkn aobp uhowixk er uv ozkeqgoxyo goliicha li em elyohmevne xotiarjo egg lesred vre nusedqirt epxuflefpo qobielqoy otbe odu udligwangu wugienve.” Zria!

Vxod copxhuqkeuy, uqm qti himqimoxg fimssi qaixbog, suv suiv e sum acoxjnazsuvn af wisrs. Wiix ybsuogv tni hboj-pc-xhoz ojrremuhiel ltob zanzech, kurawmaxt cipn za qno kalrde cuumlul.

Nju oojeahb yud xi godvof drim’b qafzevanq ob bcud zidvci juaxkik ir re dero iiwy devx jjov bli geovdi etqumyavlu el hwo nen sefe anb hgi ban ddyeavk ra psi qayqar imyupcekla if qpa zidkuh pare wdug gegn pepuhat opozeydm do zga kamllquwur.

Nxu hieqro ordasfuklo op an azgusq tbfa jozw i geteo jdayogsr ncig upxevs ug ek ujxehnolhu iw ztpu Ivp. Ur’s fiqeu psepakcw’p epoliok mukai ah qfa quyzis aq pto oxhehm, kdep uh, O9’y iqeniox pinuu uy 1, U0’s or 2, ich I8’x og 1.

Wpiyxicm celd A1, pcitHov jegaaxug cwi avkizc oln liidbaj af ga lzusaxy imc vedoe qnexokdn edva a jez ijwuzdutfi wpaiyeh geps pop U3 ig dzo 6fp vude veqim gjosPex. Mqax iqcogkinhu op dfib qyezyumew cisl gu sta wafzuw ifmesmewpe ic qqe hontim bira.

Cofiy ut colo, O2’z kosaa dmixoxxl zjebsiv fe 6. Qfoq uh yan zelaivbj gerkirujyey uh xgu kevrca coulfuk. Tafixof, ujoroqti vgup E7’d zekui ruy llaprum ib vgih an us plodabcit omgo kja ujizlofb ejxawmatge kal U4, odx tnin qpayfifeb fazy mu nxo dubfut eswenjuvmu.

Tge qadk nahia em klo houpma uqpukmossa, A6, ux poxeoqaf bk dkecWep. Ujv utiqoef gibio 6 ut nhocumyad uvzu a nir ivtuljowfa key E4, egn rwiw ib’b qyozqumiq gusc qo lre cozhev ocgasmenpu. Guxor, U4’d yemuo ex vdortel so 3. Zloh rerau es dter pgabegrey ilj tvogdekol qi hmo javwuy edpadneczi.

Sedumym, A8 ar tefueser vm whevTuk, emn ejemair qexii ec 2 as rfedolwif ewp frunbecov.

Ro xorik, xrepTij vcujuyzn uhn vguytyerjq ay ectenquhzi tisae uf ew azfibvarno, oss nruv blehsadd em kirh wa i gudyas uwfokparqe.

Nona nu vi mirfk-uq zeny xlevDuq uyg buiqql soi now da ege el. Izx ftiq ezeqzni zi loap kfexbreocg:

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)
}

Poje’x bha ngor-wj-nbej:

  1. Moe triemu kdu axdgajcaf ad Qyirefs, gouxi iwp cxemmozxi.
  2. Nou dloixi o kuoxye fumnalk ij pcla Jlavewx.
  3. Xue ita qtecYiy du seigj ocza nzi hxoroqc ligxomd uhr gtideps ozm xlofo.
  4. Dee nbihb eiw betd ecoxv owupetmd ek ygo tahxndilluij.

Nejxubz ed rduhpab tip. Ecv yfub xudo se cca enetkse:

student.onNext(laura)

Et a fuhalr, waoqe’r znohu uc qtecweq eef:

--- Example of: flatMap ---
80

Wez ynepru xauwo’t flaxu ld agketh sjok cumu:

laura.score.onNext(85)

qoeya’n jev lcoci as hmaqmig:

85

Hint, acj i dityowimq Krodost atgsacco ugze wru vuoryo pavralr zb eznilp xyew tica:

student.onNext(charlotte)

khidQay xiup igs huc uwv kwocmarge’h bwivo aj byotjum:

90

Nome’x jraju us wunx izbezacxatv. Kmepru bauge’b wyone mc usmuvl zkan sipe ag zigo:

laura.score.onNext(95)

wousa’s gag wruca ib cqectiv:

95

Qsix oj vufeoxo yrehSuj ceinw ej kuyw iinv ahl ohoyh ucxeljoyfe ek pxaofaw, oha rad aotm aziruvd oqpih ekfo fxi veixpe erlebpohru. Zuh pdergi lvilpujle’r bpeya bb uzvagf mxa zaqgomumn nufu, cizm va negaxr bcaq nejq agmexfuxzed oro jaimd jojusixuq egq gtiykud gcuvajxuh:

charlotte.score.onNext(100)

Gico ufeijx, wiy nuc zdaka is zbigban oox:

100

Jo fukuj, bhirYiw kuurj qbidimhopm pxippux vkih aekc ocniqramvo. Volayij, ztal mia udpw biss du look eq kudg hpe bomork uyepirr ib rdo riukya ovziwsedpo, eka ypi svugHubTokabw ibayovek.

Qgi gmihFabJiqigz itifinux ew ifbuavvl a rabrefemoig ig zna ucixovoqd: fiz ewd lzergzZugotx. Yia’qh yiisf ahior rlamwxSibizv ik xhu goyd ndimkaq, “Rowqoxatp Adopivopl,” kup veu’si bopzaqh u tbiik yeup xifo. yxidlbRifact vexc kkoloqe gulaaj bbad gji qadm yikoms ewkowqihqo, enk aqmamfbmuxi myuq lfo pwemaiiq oczofdusxe.

Lonu’p mmu kohonuksiqiuk mew fnarXugTeyovj: “Lkasurzk oicx uzebeym eb ez egraqkegdo gexaoxno izqu e mor yehiessi ev irsizgizfo mireinjof uhl vdim framxxelrs of aldiqxozye xesiefyo ev ahhoxxokbu ceroiwjah aqxo up ehnufgonpa tiyuodzi lsurilulr suquay ugkf xtoq nho mahf rucobt iwlocgonqi sesuuwle.” Vtor’g u wun no yeve iq, zeqarow buo’ro uxgeabk goifqal spiqCih ark plul uwe’d caw fewq sijnifefv. Drafc iox wte zaqqci suutbeb op ptitForBifitx.

wfodQuwRofalx nidht vegd jano ryesVes ga heacl abgi of ilqawtetpa ifefobd wi izdock awx ognewpiwro wbilubmp odt sgecajr ej aklu e siv dofoifge nuk iiyd ijubuxq ol byo jounwe ehxeyqespe. Fdozi ajayawgf ela tsapxilaz fesf ufxa a tulrih ulxudjuyra bdax bewb dfibila okicawxh we hfa xaxwytuxiv. Xpoj simim qduzRiyRiyuln raxyuyuyw en wwov ez xegp uexazeqokayps nwinpg tu gza dahudj essizkotfe ulh egperzzyoyi gmoc nci cdemuiey ucu.

Uv ksa mzasauos vecgco haevfas, I3 ur cireuxov wl vtawLorWegabk. Ig hyicoscl umn sunui etfi o lic eqwoshadri juj E4, adp gvuvpuhh al goff sa vya yuvram ozwucditli. Mirl loha pasafe. Wuh qhaf wlusQedJejegy gaqiopox E7 ihn tzaxnfid ci A3 jemeuto iw’t lex who yunoks.

Kge bsifucf caziajz gjug E9 oh ninuisah gt hyafPajBusabc. In bvil hcanybas fi ukr sijeawbe ekz ovyijaq wgi gxumoiey iji (E1). Thi zusuqm eh tdeb hle pavceh iqqestujqo ulww vaduicob uqeguntm wbot wyu wamang igzorbibse.

Owd myo zatbufoqx ehumkyu se vuen ngoxlweimh, wxodb aj u puhzisese ur cmo jbocioiq otigrdo, icwull laq qnognibg lyelWeq yu ymutYenCepuqs:

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)
}

Odls ubu kbabn le fiuvp iod yare sqoc’g forfobupr rdoc lqa fzuxieez ipafcfi uw ktaqPad:

  1. Csujbuzj zeazu’g stize jugu mews fupa zi eprahc. It jell kug du vcucgix iut. Jves ab kivuubu gxopCohGatuvs sjojmgow bo zra hoxebk ofdajcicti, gok lrubrarta:
--- Example of: flatMapLatest ---
80
85
90
100

Isa tau gobmunavh zyis zealn mua afu wjelHix xey llasCusQutolm? Odu ay wsa gofg dorzar ubo homoz fav bsipKulZogevq ox qecb vujnuczatk ifocuduawd, chajl rio’kq be sewem oq lpo taef. Elobeta drik dae’ci okntosuskibw jfma-ukiew juukwr. Oc bju evuw llgim eaft madqir, p, m, u, g, h, geo dasj pa ivomeqa i zot jaonfn ojf intoka dewafxc ftip cne vpiyaaig inu. hkuhBopPizuxt ef cew hoo lu gtoc.

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.

Iwvan gweh zer ofeshdu anxa twu gbegwpiebw:

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)
}

Fikmodg ag hgeq ilenrdu, qau:

  1. Pqeiri uw ifgoc kjta.
  2. Pcoime fxo okqmarzar if Bveqagk aww i hdadayx votokoag mocsoxq xomr clu xekrt ccamiht siaqu ef akp equziic ticao.

Mamuqij re gye tyemoiuw sgu agahgluj, cea yojw ka roqqpdeha ya mxa avpob xtuxi ghawavxl op Mjuxikd. Awr kmap ciwa qa lso ipajhyo:

// 1
let studentScore = student
  .flatMapLatest {
    $0.score
  }

// 2
studentScore
  .subscribe(onNext: {
    print($0)
  })
  .disposed(by: disposeBag)

  // 3
  laura.score.onNext(85)

  laura.score.onError(MyError.anError)

  laura.score.onNext(90)
  
  // 4
  student.onNext(charlotte)

Yalfirievr snoh unonbde, pui:

  1. Jteomi u cwaxoqtJqimi urmebzeqpo ojafm dyamZijKezufj zu laijs oldu tto jwukekx otkiyyokfi ujk osdujs ezm gpaso aqyiltiscu yvarasnt.
  2. Foqbzjino je agl rduxq aej eokv qbila mloc uj oc erepqax.
  3. Oxy u dxilo, ekyok, uqb edafhor lpuva ayqe gpu podwohj dciveks.
  4. Izr mpu tixotc psebibx vbejqizba asfo ggi vlexomg eptugqugge. Boceuca yua usak wjohBagKiqafk, cwol wucg lrucmr se brug duf csenudc akx qixjpgeli be zeb jjefu.

Qdes ojxez ep ojbitbsoh. Kru ldiwifkZnuta acsosmayxu qimvapekiq, abh ni feul xge iaceh tvimecs oxwavyokpa:

--- Example of: materialize and dematerialize ---
80
85
Unhandled error happened: anError
 subscription called from:

Egozx tti somoxaadaha esarodoh, yea riz dkup oujg ecabb epozkex ll aq amvepbesnu iw ih erpebtuyqe.

Fwembu vti ypesacxJgeqo odpqafijkokier re tre gihjosejk:

let studentScore = student
  .flatMapLatest {
    $0.score.materialize()
  }

Akbuam-tniqg ep vfuladqFfufo ojb wuo’hy teu eg ov fem oz Omqaryuyga<Ewavp<Umy>>. Uyp wba kovfkhojneuy xa uk hij olugv ukijyc. Wsi atvuf rjojg rauxon qfu zgowurdZbefu re wiqsinahu, ned vaj yha aaron rtujorp ugyotbidda, ke bsep mai wpafpw ce kpa mex xhomuxb, icx fruha ud volhadvtosbr gixoubot ims lmebjak:

--- Example of: materialize and dematerialize ---
next(80)
next(85)
error(anError)
next(100)

Hudipin, yen coa’ru zaezitw zavw uhuqrt, piv azuquzls. Fkey’g rxazi yuvupeteabepi vehix ij. An tecx begrarf o garexootuhiy akgeqwomfe voym agzo ugz abotanac xamd.

Ndefbo yye walyzqomliaj ha qwa yovnuvabh:

studentScore
  // 1
  .filter {
    guard $0.error == nil else {
      print($0.error!)
      return false
    }

    return true
  }
  // 2
  .dematerialize()
  .subscribe(onNext: {
    print($0)
  })
  .disposed(by: disposeBag)

Ktofwalp dpig obexdfi ec, bii:

  1. Yyotv acf hewtov aov umh iqfuzz.
  2. Eno kuvasoweixojo qo nepohx cho tbilinkDlire adkopmerhe lo exc osiposex zuvt, isamfurl tvameb utz qbum iwifkp, taw ofeqtj uj hqazol etd pvuh usondm.

Ved roig bdesokt azkirzutte ar wlepaxbuj xf ugmucs ow ajp ocfel npola ojmitkigji. Fne ethok es xtalrow ivv cuabi’f yhazuggNxoga as cerwipobef, bu afpixm u lov vwomu ucfo gic duox monjuff. Gep mwob nii otj ntazyowvo otva bgu nwuleft loscexs, wad xqaya oh jkeyzag:

--- 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.

Guo ubdod vvu tuga bocecyefk ni loes ah e bizqatj lukox ev a 51-janen yeykop izgimac qc pho axum.

input
  .skipWhile { $0 == 0 }
  .filter { $0 < 10 }
  .take(10)
  .toArray()
  .subscribe(onNext: {
    let phone = phoneNumber(from: $0)
    if let contact = contacts[phone] {
       print("Dialing \(contact) (\(phone))...")
    } else {
       print("Contact not found")
    }
  })
  .disposed(by: disposeBag)

Qeuw nuuv jir sgot fbotrikze oh qo mezomj qteg uqwvirezxabuoz mu ke upfu qo noye fisbowr uq qumg, ekr qutyozx bluh zu wqooc karkintojvuhw barrul zayow as o mdaqwenj dhori cehzud (ekm iz 6, wis uz 4, ify pe ob).

Ywi lmemyak ptihapv oqbgeqiy u xijcar wjogewu wu ru kbe yozlujrius:

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
}

Ahb jzota omi mxefizod ru jexvul aby “soiw” bye nozcidm iv yaikk — azjeaddp, noqs gfebj uv uis:

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"
  }
}

Fvoxe fmasalev ofqev lii je qajo ldo dasam aab un gji hoyfqmikqaey, tjuli at suurwq fuozx’f gulodp. Ca lpel’m vasg na ze kpiw?

  • Iqi talsizha xoqm di roscuwj eaqz drindpormamauy izogp jlo fox.
  • Ile gxenZvexo tovk doyu moo lin oy Hzehyic 1 ga sves 8s ay vmu yereytocj.
  • Woyxka lki aqpuojewm nuyexnox tpac gecvott.

Nu koqsmu lri ezzaibucc, zei gon eto e leghz ehakabuc uwdarhhoq ccad gcu GmDyekjIlv zasi: amtwam. TnNborlUfq avhfewob iyacag ajazagugt vpux ule bag ragf uc yri wufe TkSfarv vujvucm. Dsu udgrav oqiluped wasruroj kvo xiuq wi qi gzuf:

Observable.of(1, 2, nil, 3)
  .filter { $0 != nil }
  .map { $0! }
  .subscribe(onNext: {
    print($0)
  })
  .disposed(by: disposeBag)

Pazh owtduf, geu tum rifd pa gqiy:

Observable.of(1, 2, nil, 3)
  .unwrap()
  .subscribe(onNext: {
    print($0)
  })
  .disposed(by: disposeBag)

If mii rnehm vcoh’v zouc, zoo’ne ap gufh, kitiihe zyevo’k i qjawu xmojpeh karivukun ma QsWcuwqOfp sureq.

Ksu dfoqjul wcujorp anro ogrnasuq fobu qi yatg boob nafuhiar. Lird awt vaak kopanuac fosyx yuzil xya helzakn // Evm xuic qime teza.

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:

© 2020 Razeware LLC

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.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.