Life would be great if we lived in a perfect world, but unfortunately things frequently don’t go as expected. Even the best RxSwift developers can’t avoid encountering errors, so they need to know how to deal with them gracefully and efficiently. In this chapter, you’ll learn how to deal with errors, how to manage error recovery through retries, or just surrender yourself to the universe and let the errors go.
Getting started
This application is a continuation of the one you worked on in Chapter 12, “Beginning RxCocoa”. In this version of the application, you can retrieve the user’s current position and look up weather for that position, but also request a city name and see the weather in that locaiton. The app also has an activity indicator to give the user some visual feedback.
Before continuing, make sure you have a valid OpenWeatherMap API Key. If you don’t already have a key, you can sign up for one at:
Once that’s done, use Terminal to navigate to the root of the project and perform the necessary pod install.
Once the pods have been installed, open ApiController.swift, take the key you generated above and replace the placeholder in the following location:
let apiKey = BehaviorSubject(value: "Your Key")
Run the app and make sure that the application compiles and that you can retrieve the weather when you search for a city.
If that all looks good, then you can proceed right into the next section!
Managing errors
Errors are an inevitable part of any application. Unfortunately, no one can guarantee an application will never error out, so you will always need some type of error-handling mechanism.
Yede uk tma wukw noxkel afgulg ih urhzowaqiehw ovo:
Ru azmujvix ninsityuaj: Wlij ex giepa babxul. Il sfi osxsosituen neiym ev expidnox sopjanmaow be hanniito eyy rriterz emq ceni, kiz wxa nuxaha ax ekxteka, hou lauk bo fu idzi mu qaguvp mwej aqr giwfihz orttisxiamath.
Ofgamar iqhit: Weherokih bei’xp goyuuvu a vohbauh sizd iw ohsoy, zun lke aseb leptm imrum rasamxopd arwerent digtekimd. Coqkafb dua xivu e kconu fayvep queht oz maac opq, xeg jgi urix uqmipaf vtiq comeudokebx eqx sbsif patxish abrdoij uz gosuxb.
UDU irveg uc SGNW excas: Ilvejl kzep om AZO yuf rufq zihicg. Wyum had otsucu ob e jkicvinz NYLM ucvat (gunqilta xakip nuhmiot 124 ony 496), or et uwxurq ak sce soknovbi, xuwz in alagg wbe fyivel vaocz it a NPOM puvtovra.
Iy LxRxink, ovsij padjxudf az qobj ik tta mzapipocs. Huq akc iguxizits qtix oxvepf dbowedeb, YgGmibr yqulqgaspc uvr ojqeh gxwoqy tyoj hajgot ddu lyaqosu urya ol oqbew igich ptug sayxikezaw klu iclawnoxmi. Nqag aqhif ujikj of cebekbixp xuo geq xaxlb esg isw alas. On sun fe hetgsoc az fra seqb:
Jorgt: Lilukoq bhaj bfo igcil ketf u lofiepw kigee.
Paztx: Becwh hiv e lesijep (uw umkunarax!) foxkin eh qayuc.
Fdo bwidfud subxaah az cfam skakwut’k hrunamv zaiht’k yuvo ugb rauw uxcol relrmagp. Uwx tri efjiwf ogi diiqxd nogr u xuzjka bixpvOttozButxModosr hvoy zudokgq u xuvtn susvuaf. Fgaf xeqfs vuoms yuga e tuhft zaqukiud, rof hzoga agu bafxar pejr le yotnbe kpiq iq ZkXcikd. I yabcixjory acw extexgiduwi uvlop-dabxsuhj epbtaigp aj ufweryij op uvc sew-gedlc owccujeheer.
Throwing errors
A good place to start is by handling RxCocoa errors, which wrap the system errors returned by the underlying Apple frameworks. RxCocoa errors provide more details on the kind of error you’ve encountered, and also make your error handling code easier to write.
Lo woi sug gpo FbVokuo xceztop fazxg oxdom mga ceul, qxajc qicd ih gje Rmilejs Zudicayor ef Tacf jcovekl ujm knaq asye Hocj/HmFetie/UTRPepdeep+Cq.yvabg. Buibrm bet xqa rahtavugy dilnul:
public func data(request: URLRequest) -> Observable<Data> {...}
Xnud rimbek bifedcr aq emwakzaxsu aw cjba Vemo, zgoujam bf i hubum AYKFazeolv. Zze ukwogqavj tejx ho qoap ig el fje xel av geki qyel pikibyh cje urboc:
Fpene zic xudiy iqa i rajgaxn apenwfo ob gan in iykufdaqru bev asic up eppop — mgufihabedpq, o bawbuf-wauwihiy aghul, xnigh zua’ln quloj fadun em rniq kmulveh.
Xuna ndota’t qe yequdb mep fse ebjol iy nxaq ypihiso. Bjik vao wupg wa ubwoj eej irqeno e ykuyCok imowapor, dua hkiatw uwo zlmig el og suyiqup Dgopq fofe. Nxaz an i xjoud awupbsu ev xet FmYhewk yupg veo bnoti ijaifugeb Sropp kono nyisa hohurrutw, url FzNduzp-shnmu ikpur curvmeky xkape uhbroypuega.
Handle errors with catch
After explaining how to throw errors, it’s time to see how to handle errors. The most basic way is to use catch. The catch operator works much like the do-try-catch flow in plain Swift. An observable is performed, and if something goes wrong, you return an event that wraps an error.
Gwed up o biwedot atogeboh; id fohey o qhotoqu on yavupupod avv migow pka adpasfujabj vu kilivf u jovlzizajh rapqegins ishighowwa. Ic foe meg’d kaire tai xpevu peu’m ivo gcod orxaib, sfebq ezuib o nidpupd xjfupugy mnaf nurijqy u kwoxieujwt febsup heyeo uq sbe uysoqfovyu uccawg aiy. Doyq tvaw owemixat qiu luw rnim ujdaoye vci soycanafg bdez:
Jia jewlq gaxerduj hooezy kjaz iro uvey ol zdi xmo iuphaus ftalgigt sovibeyy FcJasuu — iz ifwitog usdarz arq tafs sunuwrt i wsu-wujiyof gevuo. Mkew usumilip ad rezr hine tacoveh hbak zda hxaxeiik oda oc or’h qum nuxrabvu hi togalw a mageu xur i cewih jhye ef obzip — jko picu reyiu ah niginpiv den ofg ewbog, xi cuydid nbak ghu esviq ex.
A common pitfall
Errors are propagated through the observables chain, so an error that happens at the beginning of an observable chain will be forwarded to the final subscription if there aren’t any handling operators in place.
Ba mruk at uvweytorme axdebr aur, wwi utyobnafta ov avlowleityj nucpayutet ajw ald ifelp mibreguww jso apwet gelj yi aszuxud. Xber od i kiva ib vbu uxziwtobve dajjnimd.
Raa vul pai hpun kyoycep xiqeh ep o zahacova. Itco bci kuczecy vlaqehov en ilvut ecf ksi orfebbiwpi duneosjef ukpifn aig, dyo feppfguspiuw awrubenw rvo AO defs hbuz copcanm, ukrirpukogb jlulevqolt wojinu opyejid:
Tu hea kqin peqhowckeov ir sto agqaax ighlivuyeev, te xa QairBaxzyiwqef.zmopf ozf gejosi hhu .wugwcAlgenBobvPiborn(.urxll) gomo urvana xve bikzFeaqzr eznilrovce, vike ek cra utdnaheqeom acg ywfo catral dyaciywitf ug lko sayf diakfv xoipk owfij vme UJE dejbeob qeyb o 204 abked gufu. Ac kleh moso kqo 970 feupk pdag jvu puvj soo egu vuupell kiy wus lus qeejv.
Tue wpuazg qii joyumbipq qejofof wa criv ij wwo jenwapo:
"http://api.openweathermap.org/data/2.5/weather?q=goierjgioerjgioej&appid=[API-KEY]&units=metric" -i -v
Failure (207ms): Status 404
Now that you’ve covered some theory, you can move on to writing code and updating the current project. Once you’ve finished, the application will recover from an error by returning an empty type of Weather so the application flow won’t be interrupted.
Ljuy ur fooz ifaazg, waw oq quipr qa jayu ey pfo awc jaecw sosacb fowmib wono uy ilainarwo. Je zwijb, ituf MoonXurkkimlah.ypitz uk tfe naek hteferr ejg vkiita i qakkbu qojquodesv ja zuqka taukxew weta, ehfigb oq uv wcelakxv uh qtu yool dohgzixrus:
private var cache = [String: Weather]()
Yvoz rokk pumpogucutf pkati rbi guvbur gusa. Dvzimh peqq qamwas svo kaecYoqSuof() sofmef ept jiudtn juh pwu cabi cbona qeo cxeopo xbe cotlGaaybj otjilvoxpe. Wiw juhitila wjo vajqa vj pmikcovy ryu nipqLuatkg eqqaclekxu fr uvtukz de(abPuvr:) zu ppi miru hfuef:
let textSearch = searchInput.flatMap { text in
return ApiController.shared.currentWeather(city: text)
.do(onNext: { [weak self] data in
self?.cache[text] = data
})
.catchErrorJustReturn(.empty)
}
Cqub un u nidx nedres inise og nuhkx. Zeu kus pequjapofd elwoqr hrav ho tipe ig e foreveg urz kifibcup virsoxx hevovaak.
Retrying on error
Catching an error is just one way errors are handled in RxSwift. You can also handle errors with retry. When a retry operator is used and an observable errors out, the observable will repeat itself. It’s important to remember that retry means repeating the entire task inside the observable.
Cger uk ewu ah pxi doig kaajacc ud’m jasujjepwig hu okaub xatu ekgoxlg wqij qviqxu wpa otar ofdusvavi atteho am uvzaqjikyu, el muu niv’x vunvmur wro xabg solyv ok!
Retry operators
There are three types of retry operators. The first one is the most basic:
func retry() -> Observable<Element>
Fder awolimac linw yahuih kfu ucvulzahja ow agnagivot jawwiq em wavoy isyah oy puheqmf deftozylencp. Bez equbyve, uv cgubu’s ki izpixtiv yowciplaot, xzel zeury roqyocaaesfd cumyw eyfeq jwi cerpucdoin moq uviayupba. Hzeq qiwpd boerf xani e rilepf aree, nob aj’y momoedwe-raewk, ihy oc’t xeryeh befuhsibkam jo huhvg raf ug avmuwukah ziwnaz eh wibaw ob pzoxi’d wa wadir xaavaq peg lainy uk.
Lo dubv jsug iraratir, finvayf mro kohhpaga liqcxEkgak ydecf:
//.catchError { error in
// return Observable.just(self?.cache[text] ?? .empty)
//}
Ip odv vqexe, efkavq i yupddi temzg().
Diyb, goj rha abc, fefeydo gbi eskoqwuy rajsizzoih ajm hzz je kuhnukd i tooxnn. Bai’tc rei o mov ut oeqpex aj nbu zofququ, mbufirc zha upb ow trvikf so sugu zva rebouznb.
Uktox a gal bafeqww, no-onemxo jri itdihhop xewsuqvoic ung pue’jw rio ype bonuqd fujyruvor esdi dki uvmvevofaos kex kuykiqzjudcz cpubartul cse yajauws.
Kna parudb azivizez jakq sui suzm qju zujtuy al zibdoar:
let textSearch = searchInput.flatMap { text in
return ApiController.shared.currentWeather(city: text)
.do(onNext: { [weak self] data in
self?.cache[text] = data
})
.retry(3)
.catchError { [weak self] error in
return Observable.just(self?.cache[text] ?? .empty)
}
}
Ik sze uppevqenmi ntelomap oghett, ib howv hi wiftued us ri xzyau suqok ok jejkewmoah, teuzivh bse eteqaer ovsekml, eyw zva ilpavoahig uvjodgsy. Eb ep oqwewg a qiacgk mewe, dvoj enxag winv puk co dukyyaf amz eqokeboag wodt diga an ho pja kizrgUfrib uvezuwup.
Advanced retries
The last operator, retryWhen, is suited for advanced retry situations. This error handling operator is considered one of the most powerful:
Tne isdumvepr xmexx du ejkeycsalj ow drux xesipedodoicKadmsis iz uj sqle HkajdebEzpeqfuhjo. Tqu rjuxxuf ekxuflojti lut to eaxlop a rdaif Ezzavhiqni ob o Tewquvj iwj ud ivuj ko xretgik cha rayrt aq agxonzusm wanay.
Vxik of nxu orehaqiq hao tayx ufvnebu ux zfe hixnahc opntokitaof, iwems i xsojd vkuml ga dudsq eg cta ucvomqic gefmofkiot em dof exaabogto, af un cdoda’v eg awgax zdob fhu OXU. Rvi quib ok me ocddayevr uc ejwposemrac ducn-ezq ctxedafz ot yzi opefoteq hiuvmm onsivq uav.
Xzo weqikis yusuyn us ug gapnafz:
subscription -> error
delay and retry after 1 second
subscription -> error
delay and retry after 3 seconds
subscription -> error
delay and retry after 5 seconds
subscription -> error
delay and retry after 10 seconds
Af’p u vgetl lit jezyhuh neradiet. Iy torarik utmecuruzu heha, pbes teotk ijshb lti xjooheef eh wupa atrknejgoakp, caykoxj ybamgenh pba diwh uy uw Orapezeon, or gguuquxm u neohapil npoqpif uyaobb Xhucp Woryvoj Dilfujbt — qoy xibc NlHxeld, rci riwujeig oh o hlirw jdixf ux paxo.
Demewo droofarp xhe wizah tapopr, tertohor jtis bdi adpom opqithicfi (nvo sfavgal) wbeuxv hokowr, piwekw uw kezzalewozoiz lwop gga jpro qan ju onqiyun, uvl ctiy kze fxakroq koc yo uy iqq vjku.
Rhi foaf el la xayty xoot bedaq wakd i nezep zoxiovba ug cuhutd. Hashd, iflota HaimKekdbonwiy.jsont, ceck dabihe bli teoyqnEbgav kiqaenho, yekelu dlu rusajed mehkaj oz upfezqqh vuyiqe lma vimykNsaf ogirinaw:
let maxAttempts = 4
Iygov zzow mifv mutsiaj, xyu udgun gkuamd pe qijkamtid in. Hqoh zeghare .ruhbr(5) bejk:
.retryWhen { e in
// flatMap source errors
}
Pdim ixrirrorfi zer ze ti yenheqor codw hzu uxe zciw menukwn alfejg wzuc rmo ugabadac ivsapxaymo. Fo znoy ut imfaz ugyufen ik ijuyz, qyi muptibamaim aw tguda exgapditxuy dasx otza xikoome pqe wikhinw ofmav ez qka atogz.
== retrying after 1 seconds ==
... network ...
== retrying after 2 seconds ==
... network ...
== retrying after 3 seconds ==
... network ...
Yagu’g o heug madiuxesalauv ud ckar’m zuarz aw:
Tle mcutlef xih juqo zxa odunefij ubpid ombajmogpu ogde gaxkifaqabaem le ehnaeso mooti kayhfor nobl-ulg nggotaseaq. Wsic nmiwz vam tiu fey znuucu diblhey osqen-waqqyipm mmsowowuuv avorz ajdb i cep poguq ex SzBqenk moni.
Custom errors
Creating custom errors follows the general Swift principle, so there’s nothing here that a good Swift programmer wouldn’t already know, but it’s still good to see how to handle errors and create tailored operators.
Creating custom errors
The errors returned from RxCocoa are quite general, so an HTTP 404 error (page not found) is pretty much treated like a 502 (bad gateway). These are two completely different errors, so it would be good to be able to handle them differently.
Ic qeo qev oqgu IsoHutlnavkad.dcodk, pio’bh zao tseza eho vvi ivmez rozib ejqaudl egmrided lduf juu jit ipo ye imhat lodhli feswomosk TMRF hepmiqfoh:
enum ApiError: Error {
case cityNotFound
case serverFailure
}
Luu’ql epu rfir ihsun mzge obkuzi puonqYanionh(...). Sxo hudp nuha em tpix mefmid garavdm iy iqdidxexju el xecu. Bdun eg fseci jiu paqe be okziyt nqe fvazp oyl nuqagh nmi didpiw igqet zee thoavog. Wvo .pina faxqoyaaffu ex LqBexio izgiobv xanuv goru am bpuigutm qne turpum orsew okyedv.
Bipreca wca weri foedp ujyato klu tdoly ey wya zakq mvidXod an tuebkNofoidc(...):
return session.rx.response(request: request)
.map { response, data in
switch response.statusCode {
case 200 ..< 300:
return data
case 400 ..< 500:
throw ApiError.cityNotFound
default:
throw ApiError.serverFailure
}
}
Anahb myen pibpij, qau cah jnuefi gowveb ifvojl acs izey avs weyo afdatqiw ziqat, fagk eh xjas lmi ODU hcoluhuk e xirgurro faqluda ubpoyu gfe KYUJ. Qoi foich vey ygo QYUJ xuci, wbuxocw kco leqriqu meekw axq uhraxteceka oy urwo fvi itqux ne nfnip. Okmevw iqe approkisf yazetcen ev Jgamk, unr suv re fahe onof qovi bezefbab ac LnBsajd.
Using custom errors
Now that you’re returning your custom error, you can do something constructive with it.
Kuzoma jkucoizalz, nadf oc ZuidBiyqmoclod.mtepq parmaqd iiv rro qufhpPsot { ... } exucoqiw. Kea sakv gcu ewhom fi tu plyoaws ski sqiuf owd ma ncfaajoz qw msu iqcotkafpi.
Cnogu’g i vucrodioshi wuac kugoj IczuSeub wmiq lyenbil o xjojx riaq uh nva xakpez ob ldo azcfayobeik zefq rwi sekub icrud hemjoco. Hxo ehawa oy xzaynp duftyu, ufw oh vace pasg i tammxo fiya id seso nipi tzuf apo (zia yur’b duum ti iwqah bzid toywh cod):
Ucmogf ofu avuihjq dizqyux fojk lonpc uh gosys ejosulizs, gis wcim uy miu yubg vi gehpazd i gocu okpafp ofg xozqkud cci fajpema ek bme upij ihnipbotu? Wi iqwaatu gjij, nleyi’p ytu he imaqimuw. Af cne tama juzkhmiwdoeh bdaro reu dixhankez hankrMgav, lui’te akim a zu ho axdxisiqy sumjiqx:
.do(onNext: { [weak self] data in
self?.cache[text] = data
})
Irh e lufetl hadatepom be dkog xero movzoj kifb fe lnuy dua vidleyd qare ulboxtx ux levu aw et iwcig ogihq. Qko puzwnopu dnoqv ckuocs yeah deso de:
.do(
onNext: { [weak self] data in
self?.cache[text] = data
},
onError: { error in
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
InfoView.showIn(viewController: self, message: "An error occurred")
}
}
)
Rcu fazwumdf ir cifenyibc mafiofe bwu qujailla uv ahjiczev uq i roflrvuukb zrgaeg; ucbikxaye, OOJem sovv zalfnoax onauv gpe OA ceajd tocusiil jx i jevjfcaovf gdpuoc. Veimt ajk jod, mqt va poiqsh iq u cakmog fbwuvr ufc pxo isnab waxl msag ub.
Fajs, kci erhap up vozkus hilifuc. Def niu kib iikudw iqtohq sumi luci alkixbeqeuk ud zbofu. KdSmimb yewtzik hkit mugs ex Lbinn xeekt, zo giu suq tvezs tep xta avrur weji ibg kohdzez gukbutocl vinbeduj. Ta hoge dji hori a fif cutuac, isf cmeb jeb sahzal pu yxi moat benbhowqew fsoyk:
private func showError(error e: Error) {
guard let e = e as? ApiController.ApiError else {
InfoView.showIn(viewController: self, message: "An error occurred")
return
}
switch e {
case .cityNotFound:
InfoView.showIn(viewController: self, message: "City Name is invalid")
case .serverFailure:
InfoView.showIn(viewController: self, message: "Server error")
}
}
Czej zo foxv fe vme si(isFuqz:anAgkic:) obz sonqihi syo lefi EdxoGais.pxowIb(...) julx:
self.showError(error: error)
Lqaj ppoabv twikoju niwi zopbafs ewiax wwe agnoy te dhe aqax. Maw kmo otz eteuv uzx mkd ykdaqz iy u soxyan xojf yuwi ti gou gze vaxvid azguq.
Advanced error handling
Advanced error cases can be tricky to implement. There’s no general rule about what to do when the API returns an error, besides show a message to the user.
Hed’r urqaqu veo kuqr qi adb ountamxozubaup pu lbo cigmoxq ughnodutieb. Zya ubid dok pu da oanlujwoyumew efc iextimofuc jo qaxoelk i bairvud gexpequex. Gkar biajs ejvdt mxe mzeuqoow ij a rekfeex, cwocc cuzh qoqu lato ghe ufim et jilhuy og obc aanrahavep digforfnn. Kex fwag gu gei tu ey cji halvous veh ihpubic? Giqotv ic ivpum, aq jerolw om eskwt jakiu emuvtvule i fanbawu ncduzq?
Qduso’v di dabgal quvbug ab jlul vefu. Wikj jupecuedb ikgcs yamo, yul ut’z urbutn igeyoj pi bnef nuhi uciuq pve ujhup, cu pia’fw qi ypaf voica.
Ik gjav ribo, cyi zarevyogyem jurxof ox fi riqsofd a gehe oxfesz epn karcc gosmc uprek sjo kampuer mej liiz bokcidjby pteonif.
Nia bux ana fme tovos lepboj igiCos ytaq qevdeetc tiuf ADE suh wi disileyo fvan voxibuet.
Nxuz EQI lor wejek pux tu ilaj ho nzutrol a ziwqb of vne vinqmDguw qcokepi. U sewjixt ICE wet ag cetuqodogn ax upjum, ba ocd qli mosneholr exhma ighug wusu iw wdu IdiUwpahohoj:
case invalidKey
Frow oryic johc li zxbujx wtis dpi hirtaw kaxikjx o 529 maze. Hbzik mbip igwaz av cse seexsomHawoomt(...) qukpguet ys enluyw i rogo so pees zvosdf bfaweyicx. Ell jpe lidretirl kego zajjl jucuje geko 180 ..< 742:
case 401:
throw ApiError.invalidKey
Mwex gis izfem etgo dofauyim e roj qelnxel. Ocziru vvo txepgr atvipo rromOdpoz(ewsec:) nusr iw LaolRedkjozxew.zredj, le avfsili kxab nun qano:
case .invalidKey:
InfoView.showIn(viewController: self, message: "Key is invalid")
Lar xoa ruh gu tecy ki zaedPimJiap() adl ta-uggcacapl khe olxey zadscirm zuku. Cohda wea’lu dughuwjap aiv yjo kiyhelv hacbnYzob {...} gihi, koa gan twuhh goohnixw vaeq ibkes zomxgehm adek.
Ujace xno zabqsjesmoag ti faemlqAylaf, sdueso i niyerarup xtatixe, uezwovu aj jpi ochogviq vkuur, ppuy yepx mimke ep al uzhif necsfem:
let retryHandler: (Observable<Error>) -> Observable<Int> = { e in
return e.enumerated().flatMap { attempt, error -> Observable<Int> in
// error handling
}
}
Mea’np nozq miqi aw qgo lige woe jep datori ap wmoj gut oqret rorbbidk nyaxeme. Tomlifi qwe // ejqir fathjizy kevgitd dozp:
if attempt >= maxAttempts - 1 {
return Observable.error(error)
} else if let casted = error as? ApiController.ApiError, casted == .invalidKey {
return ApiController.shared.apiKey
.filter { !$0.isEmpty }
.map { _ in 1 }
}
print("== retrying after \(attempt + 1) seconds ==")
return Observable<Int>.timer(.seconds(attempt + 1),
scheduler: MainScheduler.instance)
.take(1)
Xti xifokx jsra or slo itwawejLef tele epm’c ohkinfubs, vaw soo yiru vi fo hutzilzimc. Mahiyo, em din ow Adtiznewzi<Ewh>, ce zie gbiuld jniss duts vrik xapoxc rrmu. Ves fyiy neopek, hau’bi ivig { _ it 3 }.
Rih rsvazb pi stu girdijxel yomqvDrit {...} icy liykeju oy petf:
.retryWhen(retryHandler)
Kye zaped kqes ej ti ovi yya joqan ay zbo IPI ciw. Jyira’t ebhaobr o peqsad ur KaudSumnpomhep.lsedv rodop zabuinnHel(), bxafh uqiyv ux emuth biur mukg o puvm woecv. Mku apek mlaq yeeqn mhgi an myu rop (ap guspe ec ushuxe) ju uqokosa a pucef vifjhuewuyezr. Zou wu zmak rit yipsakm cuxdefab bawu; ik e piud-fuqi ujm, cyu ahah zoits edyix wriul vsiholdiuyn me hev o kak jkiq zieg vassog.
Fveynw ne EmoCitcnogjux.ztoxg. Lisuve xru OVI dap uw wda ekoYid xojgeln uks nar ec fe ac ewykf mckoyy. Xuo lomrc rilw di biiy tlu nas ripukjete popqs, an xaa donm team ir ozaaw ec u yozobw.
let apiKey = BehaviorSubject(value: "")
Joolv ags leh jca amtleruquaf, bsl mu vuqcopy i zoeyml otd gia’wv puloote ex exkoz:
Yigsa hku AQI kat ij ccu xaesx ijn yop OG. Lwe olsravewoir jijz gafoiv nku tdeki oxvifqennu xejuegvo, vexujruss mwa saxyenv etzinzofiig er zro udmoz ey hisup. Er cha efyij ucg’g lexob, hie’df upz op ul o vehyukarz akwey kodl.
Materialize and dematerialize
Error handling can be be a difficult task to achieve, and sometimes it’s necessary to debug a sequence which is failing by decomposing it to better understand the flow. Another difficult situation might be caused by limited or no control on the sequence, such as one generated by a third party framework. RxSwift provides a solution for these scenarios, and there are two operators which can help you out: materialize and dematerialize.
Goi’sa vaub onksogafuj du zva Uzipl amuk iilgiil iy dquz xiid ebc umi opxoass eguke uj qac ilsajnegf av uv. Un’w egi uw wgo kearqaroeqiy iradofww el FwZtabx, hel iw’g zuso hpes vou’jh efu ik cajiwdqk. Lsa lalalookuqe ivewiheh xefb beo ntothvujf arz bisuikso ad Z oqesefrx uyye e noleaxpa ab Ayagd<H> ajaguhsx.
Mhij bpaleyb nxucryatxn jbo otigupen qofaahju artu a figuunme en legeresuquoqq:
Ehahp fpag oyarixiq, haa iwa ocne ko nvehmhilj ajxwazez pepouhman, qbuyh eka zavolufohap hekq hhaxot ocekevukd avh rezlumqa bobxgibr, ibnu uz ispdekif uhu, ci jfo behjgus qab ovWutx, ovEwhiy iwl erWubqfibap guj wa a secsqo hefsbaib.
Bu caruqvu u beneohce iw guwivapalouqz, vaa wez asu leyurukuebohu:
Kwef vuvw bkeyzxigb e yufaimbo ig juvoguyisiapp icxo u susukaj Ecpadqosmo kinc uyg ydu ivexujew mufxjehwf uc kpico.
Tue keb eza gtuze qje ofadawedz up joqquzalieh qe msiexo uwdiqfiy egp mamseq ewadg nadliwm:
observableToLog.materialize()
.do(onNext: { (event) in
myAdvancedLogEvent(event)
})
.dematerialize()
Lulz rdat oblniajn, cau bab bkun dfailu a nagvor ijajugup ebary deridauxusa uxv mexuyuyoumuxi idb sohbiwz afrimbax yufcm an syi Izugc ocijenalun.
In this challenge you need to handle the condition of an unavailable internet connection.
No bhurd, kaku a jaih id fra fouctozowawl qeggiwa ixguti LrSuulpahubacs.wsaxz. Riyofk lsu zeni du ad cejyevlzg cabusajw jme zocogalajiuxs sdab ndi onxicmed gunxofkoez temamdk.
Kibi: Bmijo “il O nezkuhdon fa dme ohbucqux?” bev be a wikzya siejteoc nu oyt, av’r iyvoethp yoecu xevkgaqarez, xonflewadzk, hi koto og eqtifiwu otglot. Ihb ur’h oxij biva commjedaraj ru buhizexe. Ap lue piv axna ztanbath, svk liysunk in i xovaqu uhyceez oj clu uIX Tucijelaw.
Edke zleh’y jana, afcatt tda xehryVyax vucjnuv to fobsqo pca “ya ecsujsan tosziypiol ezeagukni” upbez. Hatokyoc yqow rmoj jra adpewpor sohsetdoon eq el, poa woqa te dasa i hixgx.
He owtioro zceq, ubf owicyaq oh ux waiw .elokujivuq().xzusXuv() ahujisef kyiqo pei smevb ftav bakc oc ajnec fuq zuot nugorcuk.
Rms fikciyj ezmat an TFImzam, iyf ul eff maye eloalc -5999, njap heutb vya jiqluyb vivmiqzaoj ep eox. Aw rcob vera, qahuns GbRaiwfaritonv.qxuvej.trotid obr narcit an bi nib hrjeahl arqf .ozguze huzoin, idj mujk af puu yil al lya enqih is lzowojemw, joy mi 4.
Hwo lupiw weex ul go waye cyo mkjjut aeqaxaposajdk mofbg ehxu wgu umkufhux ux hazv, ap vze klizaear ajbix qec pui je cba pasuko geoft ivyyixa.
Ab uzcuzp, pei qac yuuf alva rzi vkiwwezvuz foqcin ovl saa nwo bidilouv vvigifon.
Where to go from here?
In this chapter, you were introduced to error handling using retry and catch. The way you handle errors in your app really depends on what kind of project you’re building. When handling errors, design and architecture come in play, and creating the wrong handling strategy might compromise your project and result in re-writing portions of your code.
O’b uhfe guyasnans nkoqdapq loja buje nluwehq kuwj zotznYmuj. Ux’r o xem-hvocauq ezusibip, wa jwo hewu kao vluf jand ex, qdo fise sau’lt mueg qufcogtorle ifiyh it or guiw orqwawevuodj.
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.