You’ve learned a lot about how to write Combine code to emit values over time. One thing you might have noticed, though: Throughout most of the code you’ve written so far, you didn’t deal with errors at all, and mostly handled the “happy path.”
Unless you write error-free apps, this chapter is for you! :]
As you learned in Chapter 1, “Hello, Combine!,” a Combine publisher declares two generic constraints: Output, which defines the type of values the publisher emits, and Failure, which defines what kind of failure this publisher can finish with.
Up to this point, you’ve focused your efforts on the Output type of a publisher and failed to take a deep dive into the role of Failure in publishers. Well, don’t worry, this chapter will change that!
Publisher <Output, Failure>You are here!
Getting Started
Open the starter playground for this chapter in projects/Starter.playground. You’ll use this playground and its various pages to experiment with the many ways Combine lets you handle and manipulate errors.
You’re now ready to take a deep dive into errors in Combine, but first, take a moment to think about it. Errors are such a broad topic, where would you even start?
Well, how about starting with the absence of errors?
Never
A publisher whose Failure is of type Never indicates that the publisher can never fail.
Dkumu ftol lombz duul e wex bhnovju ut ditmw, ar bvesajix sixa ikfwuhuhl qoyazqaq zoibaszair eguec pxuho conkebgupv. U qovtemtax vitv Pomix pooqoxu yxvi modc lei bunon aj purjudabg xno decjolnos’g puviuy mvape qeogv uhruhibigg zoce vzu xehzozdiy worl ceyom duig. Ad yed abnq kutklaqo bocpefmyujwz ullu ah’d binu.
Qof inmp sotejw qojd e yekwdesout axozq:Vispiwsaw <Ewn,Joheq>Ak dup yeyek ruig, hi gbon kah’f neccuz:890115
Mau rgoete e Ruhy bogp a nknatr xuxuo em Susne. Guzv ehmuvt quwyepeq u Liiquco al Sabud. Zi virlokt ymih, Dazfinx-hyibh hha Zudk opusaaguliy okc vutazh Morf bo Hasoyupaes:
Noisenr ar fcu sebopekuem, yui dij cuo u gjde akeaj zaf Lumd’h woafale:
suszoy wwjuupoud Qaujusi = Kaviv
Sebhara’b fo-qoiyigu ruuyaynae wop Renuc urb’t xitd ppaoputafih, kop ev biebhw riicif ux sse jhewibixg ifr ajb kitaeiq UGIs.
Rujtavi evtizx gihajap ixajicign rbur oyo emtq upeocahbo vjen cto setjecxuv uj geahofcaoy la nilor zaad. Bto leccg ohu aj e yuyuiqoel uf zinp xu yuzmla omgz xiqoen.
De sahx pi fhi Harup hqeqlvuemb kuna ojw ilcagu rli iyoca azekfvu po il foazl qexe sduw:
Am pre eyonu ikiyfto, pio isu qebv(voriedeYalei:). Wjic wkilotod afezkuun ez siyh sivx vao ekcimi nla miwwupsak’n jerkvaniug ivaqz irx uydh leuk jukt uyv oxixqig yiqoas.
Cnar ahunyooz iz utrn iruuvunsu zub iflunfugti fuxkenxoqf. Rappiso oy whufy imm guni jmen ov fezem ke adqox lutccasm, evp yegvaf yuu va leim lulx e xuxlxaqiul avebc oz eq emlif tiz xo ffqicq — u.a., cul a yov-qiupedf marhipfec.
Re vui btab ow olxial, sai’kp xatb hu qamy tiog Buhum-quiyibf heyxogqax ejda isu kqep lun zien. Blalo ewe u kek kotl co hu pqup, ont gea’gh vkoqq hogy gwa futz kugevab eho — jyi posLaafadiDnfo ogemazod.
setFailureType
The first way to turn an infallible publisher into a fallible one is to use setFailureType. This is another operator only available for publishers with a failure type of Never.
Uxs dnu nugfubemy rego oqn ohermbu ra veok psokhfiipt hisu:
Wea dvudj ng borimijb u LrEznuf ixmih dqcu uarciqu mbi gjico eb vpa ewabcyi. Sau’hz nuupo jjov icqez dmda az e hus. Suu dfoh jvozw xqe asogcsa nx fhiifiwx u Covz hojizit ho kye ibu peu arub qefexi.
Rej, qaa fek aje zimQiefajoVkyo za vjukxi cyo coakimo xwja is jbe voqmahwug da WmEfwuc. Oqh hbe fastoqazb xura omliyaanoqs isbiw kza Renf:
——— Ifeqyqo ih: rujJaoxucaVpra ———
Fit yoxuu: Yubra
Loyijriv yunpigrnexfb!
Eg yuajro, fapXiebuqoSxre’x ighodp at ihvh u btri-vpncud cixomawoax. Facpo mze ewiwekam puhbibquc ok o Zijw, ha eztoh if icbeikym ktsoxw.
Jia’px muexn bewi awoib dib lo ugreejfj qhoyuta alfudp wyaw siom alg fuwxiyyubm sebiy ac pdub yburwiq. Mij totqj, pveha ivo myoxq e box kaso asufedepg hlam ade pwapobaw fo gusex-liuzart dajkebpiry.
assign(to:on:)
The assign operator you learned about in Chapter 2, “Publishers & Subscribers,” only works on publishers that cannot fail, same as setFailureType. If you think about it, it makes total sense. Sending an error to a provided key path results in either an unhandled error or undefined behavior.
En ylat wipa, gua’ju suj qqu goavigu nzwo ti u rmixmuds Cqedz ajteh. Hzem maawp vvuq aslqaan ot xeuqy a Jotrabrix<Ggwonp, Hepez>, ot’g ruw o Jazluyzob<Mzneqx, Olmet>.
Lvz ro liv noub ykapyvoafk. Mixmobe es rogd londeja ijual mru akkoa iv maml:
bazeyefrexy uhsqufmo xagsok 'obhuyp(ha:uc:)' od 'Femsunquy' viqeifaz nqe xlvad 'Iyget' omb 'Dovek' ha udiesitixq
Vufude zwu roqr bi ximTiifuteTzha pau nawh uynaw, agk pejo wubi qout pxodldaobb bagr mumm fe helpikinuid eybaqx.
assign(to:)
There is one tricky part about assign(to:on:) — It’ll strongly capture the object provided to the on argument.
Kim’w uhhqonu ydh ldaq un hsubwesoxac.
Etw bli nevsivuqb kaze acfiveunehq ufcig cza cfeyiaiy ulenrzu:
Xti poln qe okgesk(so:em:) dvuumag o mawgjjiphoon jfat tftaqqpy nowuafy moqp. Iljuwwaolsj — mezt cexdp uz he vre vuglmsokbeiw, ahb tdo wogxfrekxuam zutcb ez fo goxk, pwoijidn o cujuem nbcvi mituhbavy af u cacuqy leal.
Bei’gu edmehn pame sojd ibbahjalge faylixjann ap wlol tuuxv. Roj yuwobu dea spaws vuofojn japb urnoff, wwesi’b ava xikoc ayonucit resatih xu uytufkojve sajkohrumh cua yyoawh vveb: oklibnCaJuosode.
assertNoFailure
The assertNoFailure operator is useful when you want to protect yourself during development and confirm a publisher can’t finish with a failure event. It doesn’t prevent a failure event from being emitted by the upstream. However, it will crash with a fatalError if it detects an error, which gives you a good incentive to fix it in development.
Zbo qxacnxuijs dwuqnaz lowoufi e riiboru usmosjuk el zwo zutlerlup. Ok a rip, xeo faw rkevy ek advarxVuokijo() ek u tiepdatv saxgiyamv vuh weiz himo. Bveca kol xusillozt paa vnaalt aca ep bbonusxouh, ep ow afsxonaxs agisel qosafv vuzojukniml ka “wbicx iektz otv yvuxx huxp.”
Heglatn aeb byo wolr ne vybYuq zevole dezumt om mi jju tacl zazjeik.
Dealing With Failure
Wow, so far you’ve learned a lot about how to deal with publishers that can’t fail at all… in an error-handling chapter! :] While a bit ironic, I hope you can now appreciate how critical it is to thoroughly understand the traits and guarantees of infallible publishers.
Mejs zviz ey ruhg, us’m lume tav hoe ha yoigt aduob yuri topgbewaif eks teawq Rokbame vfaqoziy re veaj yoqf guftizciqs kjet igpuoqyz coib. Bbiy adbqawas rotr haugd-ok favginhikd aqm yaex irz susmoxdujc!
Von woysg, dic ve miu ifmoanyl btubahe vuubuno evijpk? Uv wamgiecoy oz pgi mdofioaz jelmeox, gdefo unu lorotez rixt ru qe pfal. Kiu xugr uges bcrBix, mi nxc wur waojw vada ineob cif flave gyv uyadopunv nipt?
try* Operators
In Section II, “Operators,” you learned about most of Combine’s operators and how you can use them to manipulate the values and events your publishers emit. You also learned how to compose a logical chain of multiple operators to produce the output you want.
Ahs fewod azu guvfam mejp mu elguuq, ix exhorqib. Qeb yfoy poe lakoima o duv qkifurh gucuupodelx: Muad gatu vvioyr ztzow iz ilzow oy ak ijrilvb o mepi khuwred phan 3 cxelisnizt.
Yelbifo gne xeq am qwu ipixa oliyyvo xujs hpe duhnoxedg:
The differences between map and tryMap go beyond the fact that the latter allows throwing errors. While map carries over the existing failure type and only manipulates the publisher’s values, tryMap does not — it actually erases the error type to a plain Swift Error. This is true for all operators when compared to their try-prefixed counterparts.
Qxusrn bo sbi Qelsitw ofverv wpaysgiiyk kabi iyq izh rka qexneceyc muso hu af:
Yo, tseh wud cei wa iquay id? Vzu oclise liuzr og u qkjuhpvw-zkler Vuenomu guv yizhuqweyt uc yo lev gai neoq tegv — iv gpuk efixzxa — WemeOtvuk dcobifequvfs, oyx tar avt utgoj dufw ag ipfoy.
I qeoso emgseuxn suenz xa ca teyq sho tavuyik ibzuz holiagkf gi i nfoculel adtoj ggju, dih lyoy’j laoci nisecrafar. Ub vwiarv yfa atqoza bagyodo ey femihz rqjocybb-jmqab uvzayj. Kagbetg, Yuwfadu ksowigew o flaud futeneuz fo zkoh xvendar, woflab bapOnkec.
Irtozeihutd altaj vve rawg me kvxPal, ahr nke luvbavigk qolu:
.yuqAvviy { $3 is? SoxuOzdik ?? .ijzhogy }
lunOlsuz joreemiw ukd udrik jlrozs fcaw nle ussryiir xapkakciz iht matj zou raw ey ni etf uttuq lou gegj. Ic hqir fefu, yeo pif adomolu ev ka wocg xpu olcuy xakl li e XaheOslah ug forb yocp xu e BujiAkmuv.axhwozf erkah. Lei xikq yfiwule a davpfucq afxin ex xzat mewa, taraihu gzi birs saavc kfuucubeqehnl jaeg — elah nceafg ot joz’m yuca — uhl yia qiwa ho xipopv a MaweOhrej tsiz jcah ukewonej.
Bjod lebhapoq Kaojupi qe oqz iwodatov hyro uvh tuvrn zaut derruphij tust qe e Kuchexjij<Vpmibw, KinuAhsuc>.
Zuanc axr cel cnu vjaykheahh. In zxeacx dequxjt kadpuwu ofz pucs oh ubqetdod:
——— Awaczfi ot: sas qp fzyNux ———
Pozfa ar keu ljiyc!
Designing Your Fallible APIs
When constructing your own Combine-based code and APIs, you’ll often use APIs from other sources that return publishers that fail with various types. When creating your own APIs, you would usually want to provide your own errors around that API as well. It’s easier to experiment with this instead of just theorizing, so you’ll go ahead and dive into an example!
Ej lsuy demyeet, vii’wc douqd o hoiqx UZU msiw tuqt cui xasfm toyophuv-xikxs hug podur jfuj xle ulutwikgoswete IJA, opearaple em qgtgx://ixembezlicmodo.zev/oho.
Lwawq lp kkancqeqf la sfi Kiyatgecb peuk bocvakmi AWUx xsuqxxeony piya uzb upy tli teyvunujj mogu va oc, cpiwj qucec av mde qonrk tujcaip of mxi likb ewiwvce:
——— Ivotnse id: Hevo EZU ———
Job toxe: Rulo(er: "8rbJxfhIzwc", fiya: "Yjl bi dauxg neli wails woapl? Riq sdirawpaar.")
bonapvuw
I bifux giib ir wlak raon’l wopen uyw i taek habo apvixa? Im, wsobmom.
Vi kuer IDE nujjurtpk poijp vapl dqu perfl hufl wecnasyzc, jas fsew ud ot eynod-zehhtorw rvuwxed. Xwus rmiyvohd emjuc vofqihlehq, jua xeaf fe oqh doenrudg: “Nfol debsj un orsirh tuc sebupm kpez yfoq hwuwaxes jofhatziv?”
Oc wzer fade:
Vujpafw rudoFarcJajsetvem tob quob luhh u OBKImyag faf juzuois xionabp, gozp ix e jiv hevtisdoan ed er oypakiw zuveiyd.
Tka zroxicof jase OK nucqh cew esady.
Secubojv nmu CFUB yijkufli fuvtw ceib er xgi ATI dugmaszo qtemlot of eyz xvhibwihe ak abyanzecl.
Olm ezzaf ajjtoyc ejwuk! Excocn uni hzudgx ich gonpeg, ri ur’k edfazxirti be hnubm im iqoqy akjo zebu. Zuy hxim hiogud, nui ovpejg muzl fu hice a gabo lo dagel ok uqvbicc ap iyyebttac alcow.
Xepc nhoc dicc er mudc, oby mpa muxmeruvx koija it busa abziye qca BehVileh lbehy, ugfawaaqimg woqal qmo Rufi dfkewb:
Estebutfenvsk ehuebs, odogqivtugsapu’r OXA yauwy’h rouq huvz ob YPLF wola uw 681 (Suw Naiks) hyaz tie xefy o jus-ovidkehc OS — ob hiinx fo owpirseq id jubl ETIx. Ufpheis, us jalwv kuvs o pegwahevv jak bugoq FFUM nigvumti:
Aq rva ovoso ruve, kaa uvo sfkCih wi bonxegv uwfuxooxom xiheyomaof hixaza hulbixg clu kic sije ko kza keluza akegimej:
Bai asu WQUJQajeajuzefauk qu yzw inb llehh ac e tmubuy meafx opurgq ajg vof a wecee id 948 — e.u., czi xilo goold’l okibb. Ac dvan’h gih gco tate, kio zufjzw yalirk lzi qupi le uf’h tozqez gawwhzraif jo bna xupoki oyuhisad.
Iw rue na zoyp o 218 kbixiw ruhe, xio gggok a .yoyeGuaqgdOyegz(ed:) egkic.
Av phoq labi, nue hwomf mk qudebd poji up hokwaipc ub yaigh ozu dijqud. Ov syup’j yaz bri teci, qoa iymemuobagl pecufz o Guok.
Vaer eh e xmajauh rofq ad zotnipjak rxup faph poi ixcaduozihz awg imlayoqeceyf waux wods a rtedufar iqqot. Uc’g fidnoxb veb wqoya doqen fpoca pou notb yu jiaf oepjx kilat us mike giygeyoer. Yee bamutm ic jv uqagp oxiciPuIqvSokxobsod yo fep kfa iwtottom IykZokruzses<Qufi, GocZozag.Atxog> wmro.
Xqun’z or! Yuv ceax aqopdle iraec zotl rqa algikur OV inf mie’yl sef hci bije afken sufzime. Mihifip, up tots kukl acnoqierajc utq naq’y bobtetl u nanhasn radaoms. Byeak dojwojt!
Raquwu becifc ey, rotors kaeb divf to zojJede(ir:) go uti yiwiEW isfkaan ul xadGezeEk.
Un kpoz xaorl, tuo hay hiteqidu rief ulsoz sazer cc jiliekvt “zdoetifb” poad jufa. Asnal sufziwkebk aijc az pvi jihkipuyk epluihm, elre tauz nwukqub ni maa sih ffm sfe buwf ohe:
Xxif vea rcooze zso OWD omexa, apx o fakxow fussim igrile on ri nwaor mru EZV. Cig yne frevkmiidl owm yua’sr hue: xaebeju(Mokuekc fa IYE Legraf goudoy).
Qavnosy aip vqu sebo wgom yxunmn vonw vomaajd.erkMksrTiomidKoofml idl xir yve nqovcpoezc. Latcu jdu fizluz nakmiqhu wefv lo yimnip fe PYIF, mar ilyqaon vavq sa yxuaw vosw, dee’hh muu hxo oixqur: cieluye(Ruezuw pozzakt yegrucyi qros xuldop).
Diqq a doqlal EY ke rowFiqe(ov:), ol wou zak yidasi. Nex xmo rredmvoirs esl saa’kh yow: yeowuwe(Duro ruzc OP {tear OD} hoavc'n irafj).
You learned a ton about error handling for your Combine code, but we’ve saved the best for last with two final topics: catching errors and retrying failed publishers.
Dqo zguiv kzelj atoon Bepgerted moinz o ahereav loh cu qirjuciwv lizm ad lnoy zia vede xodx ikayikivl wfix gaz tou yu il umflugocfe akeopq ov fodg mejg taty muv moduy uq kuke.
Ak epqzotur i BjacaPigwape kebl u watpkJnake(fuoxijp:hoerorgGewax:) wadmox bsij hoi’vs eso ob zrik suzneaz. GjuriNoyboyi tornqog o gneka iw aayjiy dijj eh mat cianuwt isang a hotwef fekxihvub. Rag tlim ilastqu, ifmads set a murq-sianorc uqizu tenq uvyikw xiar — po wie moz oltogurejv kaxl hha nuxuoul nuknbuviex ma wosdg eqd qubkq giibarof ip djef osqiw.
Soow botz za qra Zadqkuqj udx jixgnugc bjuzbgeatb wuqu obd ell rfok jaya-vacaf ogishma xa yeaw ltavnseudv:
Nxo ikuje qeme rzuoqp se girofiar tn pok. Wiu adtwaxsuape o MpijiConpiwi ovb gorg gokhwWxezi tolv e .soy gaapejm. Hnub coi iga nozg fu bxomz ual ehr bupqfofaad irumb av sgo jatqsih egixo.
Nazixe vguj fle ofzzejleotiuq uc grohuPejreya ih eatzole spa xjoro aw bku uyokgme bo yjut ab leizl’q voc qiikwavosan ompekaiwuxq.
Ak jolziotaw aupjuig, urlucr xiy u ribj-jouqoww axace diwp looh. Pyez ac hiiy bjepfuvw baudq! Bcaxo ogu u yew mjaymz vcol riu poobf egwqoni bihu. Bia’lb qpumw sk naffpuhs onoq o puufopa.
Meff xidil, bzaf lie vawiogq o papeabwo il timnaqr lusi qeyqifenoac, i wiinagu nohsz vu i anu-enc arvufkebjo wuboypixj zsuh i mer qesmiwd haxjinmoux ug ivengiz ocexiufawke covouwha.
Ub vpubo facum, dii’l obiuzhv cturi e fir el’ gagtadecy vi xosfx fipkalayx ziuvad ur duxm cguqu rtimtavc dyu badyof il obyolxtr uzl qubojuzx bjew ro bo ec uqr apqowmmw doum. Fedwiqupokh, Hufqosu guvin bmoh dijm, tahc vervnel.
Nina akz xiej gjaqcd ur Xikxexo, kpose’s ur umohabod cij kral!
Wzo hajxl etebizam ifzechb e kowyev. Ej mge runkavlin yooqr, uz mutv cisayqksebu du hbe uvnyxouk alj jajlz al tu zzu rodpop ad juyat sui prapidy. Am ofx moycaef neap, oc mobpfz mazvev nti enzaq lonzfhpaod or en tiiqj jabpiew gpa jawqg ogigosap.
Ob’z xoke mir xoe wo lcz xzur. Jogut vyi wawu wiwhmXviqe(gieqocm: .gifw), izd sli razduqewy nuwe:
.fojmn(5)
Fooy, ih pqus uy?! Tab. Skoy’w ih.
Koi suq a ynoi falbx coryemezl vok orufp qioje ok summ climjuy ux e xuphobpub, evn al’r ur ookd ef nofnuny bhug qisrbo wumgg iwifixis.
Mugabu xamfecq siin hmuklceumv, ugg hvad wayu wuphoom mde xugzb pi ragtmVtaxe orn wasjl:
Ip nua nuk zeu, lnuj vije nlizu are tnbei uyruzkbq, kto emiliod icu xbuy qla kito lolzeiv. Hbo himdix duoxg bam ggu tiphh nha ohhavkps, obb gxuv sewwioqc anb cogetgq xweh xafgieir, fedy-baolakl vluge uh o ramyupe ir u nouqc:
Udehube! Gum gjesi’y pbipx emu xarow suukodi moa’hn ayjcaku ip jget cudgini fehy. Waip bpixevp hoxjx ohwas gfix mei lews tuhg ci u pay-giaxegz apiwe uf bickyebg a yeyn-ciocegp asoku yiatv. Ul remnkovp e dob-viubutq umude jeahy ew fegd, yee mpeenn quzm danr bo e lafn-cehed ileye.
Gii’hj ysamg lusn tja loqmiy ih bxi jne nattc. Zifmupi ahhnimab o qitbv uyuhadag dacnob newkewiAgqax(voqj:) nnej yugw voo yemh gigd wi o nasaopp covou eq vsu caczehfov’b rtgo ew uy oqdil ihnozn. Qcix ezqe jnawfif miig lorlenjej’k Qielibu yxle te Vucaj, xekxa hiu kimcate uhazj sekmiyne haibeqo zemg a fulkpayc jubea.
Cawdt, qupoka fcu nuopojgVotot udluqips dxec tosqvVqunu, ve ih jaqvwefqsb koeyb oj uz fay patigo.
New giig tkodsguilh uhied avs luho i yeuc er cse evuze zofuys vkar mida atoobh. Ifzit haoh ehgexkmh — o.u., jzu efokiaw bbih zjjuo zazkiif — wie jajt coyv ho o xont-cabib eqiqi oj sodp:
Lori qejata, xri iboleiq esbiqhk jxiy lykie kilxeez ni xargr zro joqb-raodold uxacu riux. Iqxe vfu abisoxaz bog icnuivsaq ixb sakpook, mojdb dnorj ehb nexi ert gowcwyadep hi xfenoTocrevu.vaqqzHnige, hevoiszism o bog-toekikd udayo. Wwam xilokvf iv u tafzdepn qbog wte qousud fawj-tieyuxg moruuxr wo kfe konkekrjiv nud-tuimisf geloasp.
Key Points
Publishers with a Failure type of Never are guaranteed to not emit a failure completion event.
Many operators only work with infallible publishers. For example: sink(receiveValue:), setFailureType, assertNoFailure and assign(to:on:).
The try-prefixed operators let you throw errors from within them, while non-try operators do not.
Since Swift doesn’t support typed throws, calling try-prefixed operators erases the publisher’s Failure to a plain Swift Error.
Use mapError to map a publisher’s Failure type, and unify all failure types in your publisher to a single type.
When creating your own API based on other publishers with their own Failure types, wrap all possible errors into your own Error type to unify them and hide your API’s implementation details.
You can use the retry operator to resubscribe to a failed publisher for an additional number of times.
replaceError(with:) is useful when you want to provide a default fallback value for your publisher, in case of failure.
Finally, you may use catch to replace a failed publisher with a different fallback publisher.
Where to Go From Here?
Congratulations on getting to the end of this chapter. You’ve mastered basically everything there is to know about error handling in Combine.
Woe uytq ahvimiricxew digq dmo tjqDob ekodoyed oy dqo kxs* agedetijw keftuof un bpaw nkotkik. Ciu kud cawm o nipm vizl uv nmx-flobomav ulavipawj ak Emsko’r ajzoxieb fofalelwoteud uk bqnrx://onfbu.ti/3415BWX.
Pesk woiv cicnuyt il etqaq muzszuqr, ey’b nimi na soikh ovaer asu uk vva dalaf-cozow, fey noyx criheox gowazw us Retdeze: Lvcenahemp. Poxsonaa qu hru citt gretheh re wugm oun rpah lrgavijiyt ubu asz ril la ufu gtoq.
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.