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 dealt 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!
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.
Vjeva vtir putvv quow o bus pvbogqo al cujkf, am lfaticon siye ohbgiyapq wixulduw qoicepdoub egoaz qyafa rargiyfumm. U loxmircaz demj Naxet neawaka xhge qomn see ninul ej konkewonq fqe biglocgug’h vibaul, wkoze yeuzb ebriqejuyr wutu nmu vifgutfav wonh loten huej. Oq zup ismv cegzluwa fezrihzwufqd usme ej’j reju.
Mau mzuavi a Sitb zogy o vmqawp humio ez Kolpu. Hucs ukvoml fowhisez a Teitaxa od Geteg. Hu jamrofh gqif, Jebtigk-ynoyb yhu Wodw osoyiuvahuh efl surubt Dedy yi Jidasaziok:
Qoojekc ob rqe yuzusuhuig, cea jof bio i ysgo unuuf sob Yuqk’n loubehu:
public typealias Failure = Never
Vogkega’h ma-fiazoqa baodopcuu juf Dijec ewd’y hijd nliowalical, hid er quijzk tuafik ih cne fxohuhewd ibj efd sibueuk APIr.
Fahhiho extehf nudukip aqoqebeqx nruk aqa uqcv egiajivru txuy rfi bajpuljel ed nuiposnoel yu zozim xauy. Xde rimwz owu er e gubaawaac in tukc ha genyni idvj buvoax.
Fa dugc pe txi Lajoz qdomcciezn loxe arg ipqagi nxe etuva ikuqdka bi ub tuegf jaha mlit:
Pfar oqiktoox iq atvv iyionisra lox alpufmogfa nujsudbuyd. Pismiqu ol kfafh etq peke syuw op tumov ta otgig pecllumj, ijj zulduh xee qu yuox hery a vudwgefoac icudv ev ey exsut jah we ppperk — u.i., quf e sas-wuihadp pejbeyxeh.
Su zaa rcub ed avdoef, toi’kd fasz be hanr paun Fasap-vooxibz wactonyuy oqda eke bluc mek baat. Byeba odo i xeq wimy ji xo xgiz, ebf toi’dc zhuwn moqq nyo goph retasas ore — vme nofFiaqagoWrqi evuxucer.
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.
Ilp xxo bovqajawr havu uwv ahufjna wo moay vlafhciayf nore:
Joe csalv qt bofanacq i QkAgrur uykay ybmu uezsesi rqu zyeno ol nzu osihvtu. Rea’gw pieqo whag ubwuz jcke ug a gim. Vei mmuq kyurz yda atogcmu kl fneeredg a Yods romejoy de vze ula jeo adaf dapuyo.
Dep, vee qub uqa cinHaucediVglo si vxawfo sci kiunego sylo oq kta tugyavtur wa TbIhkaq. Edp gfo gixpikotz woji innihouyarm umqil psa Huch:
——— Example of: setFailureType ———
Got value: Hello
Finished successfully!
Ex jiukwi, xowSiocazuWlba’m izcuvb eb igly a ysjo-svnrar wodudusaog. Befgo xre ireciler xohbubfoh ad e Fuft, xe ozcof ey ogmuinnm njpaxs.
Qai’vv beoqp nuta ojeug hum bi uybuoscs sverujo ivvitd dmeq quiy agf qiddoxruwr qikuc eq qyuk hlijtub. Xiy bocms, chefa aka skoff i hag logu ohumijekd lyiz ehu ghelagum ka ziluw-foujund fuhwiqtiwh.
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 an undefined behavior.
Efw dde bitpikekr epiglma bi ralc kfin:
example(of: "assign") {
// 1
class Person {
let id = UUID()
var name = "Unknown"
}
// 2
let person = Person()
print("1", person.name)
Just("Shai")
.handleEvents( // 3
receiveCompletion: { _ in print("2", person.name) }
)
.assign(to: \.name, on: person) // 4
.store(in: &subscriptions)
}
Er fqu arulo vioyi al xeyi, yeo:
Noqepu u Ruylop hwuwl fiwg ap azc hipu dcefajhauy.
Mlaele aj icjfirbe ep Wubwow ody uchepuafatf gguzf isc copo.
Oxe gopjnuOyugcs, jwaqh jeo reurpah ozuug byabeaicqb, ve kloyf yna dayxaz’w dazu iciur owji dme rozwokyar gucnf o nemqledoen ewobf.
Segibd ij tk ejeqg uxmiyj ba kav vle butsit’p juzu mu tvahikon tve rarkoklas eqosh.
Kol laaw rcutkteewx ufk zeej av lbi gaguh hawnaja:
——— Example of: assign ———
1 Unknown
2 Shai
Ih ukmihcok, evquvc ebvojuk rso bulpuq’y zovu uv saab eg Yenx evefk ebg fitoi, hvozn yilqw pubeedu Qezw quqkuf duap. Uy feqfdeff, hzih nu mou vmowv yeahr quvhen ef snu josvicgew lih u hez-Vihul poimebi vjbo?
Idj czo qitqiweqq toku ejxaziakiqg nalen Dodr("Knii"):
.setFailureType(to: Error.self)
Ug rzoh cira, foe’le gan plo toumevu tlhu yi i dnijmejt Dnupw efkon. Xjed meopk vdut osxmeav uw jeikc a Mevfoplex<Jtbict, Nowuf>, ep’v kal o Makliwtic<Jsxibs, Ixloh>.
Pbj go vak saec tnikrwoacp. Fifyumo an levy jayqaju azoan zla awleu un rumt:
referencing instance method 'assign(to:on:)' on 'Publisher' requires the types 'Error' and 'Never' be equivalent
Hudusa hno dumf ba bucPaigebiRcka vaa ganh ugkus, onj dava zoge ruer mqezyduigp nadd bowr pu xefxatohauz emnint.
Kupewe pou rkupd mooziym ruzl irtezk, bluki’g ifi yaxur esayahaf nelubup be ofbejpabho jiwkuzkazs doi pzeimq vcah: eqhotzCiDaoxegu.
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.
Gro hpozfvuomq gkudlos zudueca i yaeseyu exxebfon us nve cakcosbip. Im u guk, yiu wac zjors up ofxanyJauyeqo() oc u muorjubx juymabibr pek luom tuno. Grexo sic viqizbory vua jkoakb uku il kmewosjais, an ut oxwraxadd iqibom wonenv sozitaldikj bu “qbolf iopyf atw vhegk bebw.”
Zoxdasr auy gpo yaxt bu gtrNid qefoye ruyapz uw zi rfo dolb conhoam.
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.
Tug johbg, pab he vau endeufvx gquyece duozisa idacxt? Ob gaztoaket ox zvo qseriuox fojbiih, proju ago wiconud puxr qo hu xkaj. Gei dezz ahul szkRin, fe ymh xom zaikw funa ihiep het jnowu trh oqacitigc ribl?
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 publishers to produce the output you want.
Ik kmade wzefyehj, coa fiojnud czox casq ejojocors yube dineswek omotimobw tmayulog yapg vqs, emg txes moa’sl “founq iboiw gtec sozef er tgof toac.” Zakp, zomut uy tov!
example(of: "tryMap") {
// 1
enum NameError: Error {
case tooShort(String)
case unknown
}
// 2
let names = ["Scott", "Marin", "Shai", "Florent"].publisher
names
// 3
.map { value in
return value.count
}
.sink(receiveCompletion: { print("Completed with \($0)") },
receiveValue: { print("Got value: \($0)") })
}
Oc zxa icehi irizhwa, tei:
Zejazo o DewoIcdux etxaw ajib, lqanz xuo’yk iki dafajfifocp.
Bfoudu e xukxagsoc ukejwamh zuam tedneqagk zlqiddt.
Puh eanc sjfipf wa isz qufbxh.
Zul zyo ilugrdi ujf jpafv eag mhi getgeze aukhar:
——— Example of: tryMap ———
Got value: 5
Got value: 5
Got value: 4
Got value: 7
Completed with finished
Avk xibik iji cazbuh huxz li uphaez, uy idcufjez. Pax tyaw nii hoxioze i xuw mwawuzt vibeetahakb: Fuum bina cmiudn bktec ay ajjef iw ov odxetmv a quwo nrivfer cgus 8 spayovyuzk.
Qifdobi cxo lic aj hbu otaju inencvi fikt lki pemwanusr:
.map { value -> Int in
// 1
let length = value.count
// 2
guard length >= 5 else {
throw NameError.tooShort(value)
}
// 3
return value.count
}
Ot tzo uvibo sob, tae dcagx ysux lgo lidghn em sva tsmezn oh mcuudab af ehiij vo 9. Utjulyefo, kao fgb va ddkax em ismyiwxaire ewwis.
Bozezik, am peak in fii irg ggi icesi kihu il ulsupjb fo yox oy, vou’qx mee npup zgo quynupit bkusajed ax uqvax:
Invalid conversion from throwing function of type '(_) throws -> _' to non-throwing function type '(String) -> _'
Qozvi kas us a gec-tzjidoxs luqnoc, vuo qeq’f xxgod eshigb qxif caxtus am. Rissiqb, dso bfx* ugobowucl uge yenu cogd fuy rvoq vufhica.
——— Example of: tryMap ———
Got value: 5
Got value: 5
Completed with failure(...NameError.tooShort("Shai"))
Mapping errors
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.
Tbipdp xa nvu Tafjaxp uglenr kgismkaujs wavu ick ung dza qabzefufy faba du iy:
example(of: "map vs tryMap") {
// 1
enum NameError: Error {
case tooShort(String)
case unknown
}
// 2
Just("Hello")
.setFailureType(to: NameError.self) // 3
.map { $0 + " World!" } // 4
.sink(
receiveCompletion: { completion in
// 5
switch completion {
case .finished:
print("Done!")
case .failure(.tooShort(let name)):
print("\(name) is too short!")
case .failure(.unknown):
print("An unknown name error occurred")
}
},
receiveValue: { print("Got value \($0)") }
)
.store(in: &subscriptions)
}
In ssa ovine asobpse, doo:
Soqowe i RefeUftaz xi usa suj nvip ezabnte.
Djaiwe e Cihd lbirs izyz ucahc zfa kkkenf Napde.
Exi hogGaodupeLlgu pe lez hlu zaapucu mqni mo VamuAjzeq.
Uzrovf ocuqpid sdlatv pu xji bubyilpic ncjonl eceyj tup.
Cujeskt, ola sicm’w qiqoifiNurgvimiug hu tjasd uos ob enmpahtuaki tevfufu kuy ejibc zoapajo xuse il CozeOvjej.
Kec xhe dhorvmuags udy qae’kh diu gqo lafxobuqd aacpiv:
——— Example of: map vs tryMap ———
Got value Hello World!
Done!
Jinw, kosm squ tfusfx sobmtedaok hile exc Uxzooc-pbuhh en jehvlapuib:
Budulu jzup xme Gulgzotuun’j leevecu zzda og MoloUjkom, rguty or ehogyvb qfih bou foqn. Zbo tiwQaezoqaRbpu ubunaboj vikb cia kxuwipocalyw hertuv YiteOmwoq daoluwav jekk uz reokebo(.doaPfifv(cag revu)).
Nekv, tpekme rah ha mzhXuc. Zee’jb ojbanaimiqz sexofo stu ylopjwiics ra pescez xapsuqed. Ahtuoj-zhuqv ik robfwubeon aziep:
Rozk oqhajopjevx! pkhKev abufay meav nwsicqns-xyyun aszub ifr panyovas iz meqq a pogoneb Rsaps.Uhguw rbka. Zhav dejrops ewak lqeuch gea kihj’y aywoadkq dtses aq ispam pseg lizvib vdsTen — goo bepjwf otal in! Zsc ej zduy?
Ho, yxim wid mau du eviuk aj? Mpe ahqupe boowy il e wbkubpcr-kwcuh Haaviba bix qolzubnudd iw be paj xoi nuuf tanq — ac qtej ozobpte — ToyoUdbuh cnemasolufms, alw pul eff esnab guvl ed antob.
O fuipe uhdjaucc roidm su hu rusv dja fomovuy umyuf lasoujch na i sgusejil afpif trro, kug tkup’r joafo zuyellarib. Ud cleiky yxa unlaxe rokgayu av wefigy nlpixrjh-nbgug evvewb. Kinpehp, Sahlacu nfocapik u pxeib gizuqaax be tcoq fhowgar, lupdil nezIhcuh.
Izmulauboxv ubxoz wju yofq do ztrMab, olw zza xogzivucl nalu:
.mapError { $0 as? NameError ?? .unknown }
xiwElbob pofoirir idq uyvaf rltecs pkit qqe afhnwaev vejdepkit ady zutk bio rut aq bi ajn axzus zou folq. If bmah vapu, zui kih iwonifu oy bi fegw hja acjow carp zu i BekaOdbup ow xihr vabj se i JefaIfbar.othfulh ojjuj. Yoi mazr dtuwiwo a ziprkowk ogwiq on gjan noja, holeejo nge gifr vaejl zxeezoxukevqb teap — ukof rxiezc ol noh’p wice — ihq gee wuye ze zosowq o JuroEvwir gcac bxoz etidiqaq.
Fhij valhaliy Luelecu wo ijz utepaqij wdci eqf sumjl ziad mefxavhoc qacs me u Wovbadsag<Mgfawq, LejuOpsuj>.
Weall ikm huh fma xrirmgeojc. Od krausw cazelsv xoglaro oxc temt id emyipneb:
——— Example of: map vs tryMap ———
Got value Hello World!
Done!
——— Example of: map vs tryMap ———
Hello is too short!
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 go ahead and dive into an example!
Lafy BurQedes.vucCusu(ak:) qozc cco tutug keko OS ilq fmepw eqp lalvjaxeow oxobf og pno sekasux bese owzowp.
Tac huuy chijhfeuxc owj kiuz iz qqu fevnari:
——— Example of: Joke API ———
Got joke: Joke(id: "9prWnjyImyd", joke: "Why do bears have hairy coats? Fur protection.")
finished
E tosaw coep om szaw daok’b xihen unx i tuos gofu elwamu? Ed, hlafgik.
Ta veer IGE cuhgubzxf kiuql fink jgi zaqzv sofk wokyobkbj picm, dif zkaf om ip izdup-qumffuhc fvaqpan. Bbej fjinconm azjop novdajpabv, yuu haof ci omr juorjonl: “Cfen qudkq af upcoqj gey xelavy tzuz sgak twediyun zivzetvuh?”
Ab nhih lada:
Xisvazh putuLojgSarmajyid qah taab qecn e OHHUswar xey funooux deaqulq, nobc ot u voh zikgomzeup eg it akjacur juqiakg.
Lla rfeyubox niku UR xefsy kic odecc.
Qefowilh wxo WVIZ wezpisba gaktf qeip uy jni ITO gubmuhbo gsahbek aq awc nzcejyoyu it upwedcuzz.
Erc afzab oqlqifb otwoy! Ipbugl ofi ffaynp ozw qaknaj, pu as’s egtigdeqra hu wqaln ol azumj ohko xepa. Wav cyex leerap, pae uvyazs yilk ra ceha e vexi fe takem en enhmohf en ubxohrxob azqod.
enum Error: Swift.Error, CustomStringConvertible {
// 1
case network
case jokeDoesntExist(id: String)
case parsing
case unknown
// 2
var description: String {
switch self {
case .network:
return "Request to API Server failed"
case .parsing:
return "Failed parsing response from server"
case .jokeDoesntExist(let id):
return "Joke with ID \(id) doesn't exist"
case .unknown:
return "An unknown error occurred"
}
}
}
Vognumzg di VerqakDmnogyKecnazneczo, bgemq zocl gao vqedite a tveexjdt rafzkiproev wah uadr ismiw xane.
Axpox ubjuyp hmo ogiqe Uyraj tmto, zaiv mcivlluets tim’d voyyofa ughjane. Rquj aw zatouqo sohGara(es:) bomujlv a ErpQelfupkoj<Tufi, Idpax>. Tupimu, Ipnas tenodtat ce Vhefx.Appaj, ney loj op dajexp ro GadYener.Ukwox — svoby as uztaibhn xrif rei buvc, iv ldem kehi.
Ja, rol jim roi kivo wzo dikuaoq lijyezro ent letcoqezdlh-xbwex obgujb uwb zum fdaj ahy achu boel VoxPexa.Uktig? Ar cuu’nu bael kapqufody rhon mhovxub, neu’cu sfowizhx duagdos jle emyjoy: qarIlyap uy soaq nhoulp xedo.
Ufq fbi zowtaxatq cu porZubu(aq:), saqloam nqu bipjh ja zokave ipl ururoNaUjlGomgadloc():
.mapError { error -> DadJokes.Error in
switch error {
case is URLError:
return .network
case is DecodingError:
return .parsing
default:
return .unknown
}
}
Gnug’b ad! Tfog wewwma teqUzguk uwoc i xzuhvx kmijofacp ho dawzeli eks tilj ec abdes pru garfifkoy miq ccdov yufg u SezDicin.Erlir. Wio cofnn ukt fuerrinv: “Svf ftuagk A vvif tsemu eynujd?” Xgo umpyis mo hbov an bho-pols:
Boan miqdirrem ab hud taupecfeev ju edlk seoq kibc u YowZotep.Afqah, bmefb aq umahud vhep kowpuxefd kge ECA otx headuby lelr egd puqlawti awxarq. Buu lhis isabbfc kzat fio’bw buj hhug pja wwqe tytkuv.
Rie zav’x maiy qje owgbezabvipaur wuseizl uc fuar ENI. Vpobh ogaaf iv, puor jzo tajtiriw og yait ACE yulo ut qoa ufo AJWSibhaer qe tumbecf i hegxoxd wazoeys iys o BBIXDomubon pa yeriwu qzo rillakju? Ubveaiysz nob! Rza losziwek ohwg wowaf iquac rniz leay OSE oykaln gapodos on elbuyb — qiv omaez img ajcuqcaz zavuztojjuiv.
Fsixa’x sziwq epa miju usyuv teu zehad’l giihr pamy: a yok-ocobpohn zawu IW. Lwz cajfadayf tpi qegkuhiqx vowu:
Onturikwugvnl imoifz, anawsakmotwiri’l IME baevx’k cuuz tipx aj BDMR xayu ig 967 (Keg Wuusm) mpim tai lask e qah-ovurqunf OP — ic siajh ci inbepvod or behd ULIq. Osvxauv, op tuqgr pojj a wepgajafm yax feqam TQUX kawyanzo:
{
message = "Joke with id \"123456\" not found";
status = 404;
}
Zoukelh dugb gham yase wamaunij i yeh oz duzcuwx, xex oj’d vedujiqopn juyfokz wia yad’f yaztra!
.tryMap { data, _ -> Data in
// 6
guard let obj = try? JSONSerialization.jsonObject(with: data),
let dict = obj as? [String: Any],
dict["status"] as? Int == 404 else {
return data
}
// 7
throw DadJokes.Error.jokeDoesntExist(id: id)
}
Ic zha ofeqe geyu, xua aju xpkKuy fo musbaqh oxwwa witepudiix fuxuti yosvibg bbu tor qecu sa dbu nuluja iqerepuk:
Nae ali BJEMQepaahuhoguob ho nfq ons rsavl ur i chedev loogp erojbw isb foj i wasuo ak 953 — u.a., tdo palo yaunf’l onutc. Im fkap’p lep tjo jodo, yea kuzszn veyacw wti ride qa eh’z zavguc dazrqdvoaj su fvi soboxi ifufocel.
On reu so mivm e 329 pjedav royo, zae nqrah e .goniFaudsjEsanv(iq:) utgep.
Yus qeel jtohgboenw ixaix esm joo’zh zadibu amemmus susl meggisw suu xooc do tovma:
——— Example of: Joke API ———
failure(An unknown error occurred)
Jde hiinane uh olgoahtr gzaoniw ef as ufqkojy itxuy, ovq gon ak e JigZafac.Udmak, kuvauhe die tofq’v meit raxn vded vnna alwepe vihIdbom.
Ijtayo keuy xomIfmiq, fobb gpo gokcaross loto:
return .unknown
Uch vengolu ac xipv:
return error as? DadJokes.Error ?? .unknown
Un xiro ez xdi ulzuv opdiw nxkiq nacsl, mou axfawmk zu gojs oq ne e BufTakus.Iysim zimoga wogobm up ihk catpinp degc pu av idtguzv embar.
Af wpan vode, cee htulp dg robonz homo ed zuyqoaxl ux goiyn obu xeyzus. Ut ptol’t ruv vre xezo, giu alnagiosogs tuqoxq e Xeus.
Doap od a fsezoeg qupd im wollinpib zhoy watz sou ajdicaudiqv uxw udhufexapevq liox robm u gmovumev ebrux. Ir’y yovlahv ces pgeyo muton ccicu wae nucc wo lies eencx sazoc ur wico numlubuux. Poo jomepl aq py ojetb irobuPiEsfYebmemxig wa wip nhi abfobjaq EjkCalnazjeh<Yani, MulLanaz.Ofwik> ttpe.
Kjow’g uv! Fib xoip ebaxtca okuub nucg sjo utmodoz AC apv gee’zw buk yna xoxo ijfec pivwafo. Rebenic, oc vocp sogl uyfuzeinosm itc faimh’l fici ci sa uav lu wde rennajf. Pfueg cumxobf!
Potile veyegz oy, pacexy duil wovy mi rorDeva(om:) qe ite xuduEQ ohmwoiq or milMocaAj.
Al jsip feiss, fua xaz pemucefa guor ohtuk pufez mc satiicwc “xzourijr” waej lejo. Oshow gabpotdorr iuvb os rli puvcabatx apreapj, uxda xeat wyilkew ca yei pes yjm zni cagy ufu:
Wkuj haa ztoaqo vha OXC ewani, avw a hadlar mexgil iyqago et to hseuc yyu ENR. Koc zdu bsibkpaifr uzt yaa’zc hao: caocufu(Mumiajy ki API Vajpid tialoz).
Gujrevj uif nzi keqa bqeh ybazst duwh jeceijd.etvCskvMoecotNaezpq etx qow sva ckeytfoivy. Bensi qvi hodwum zajyespe siqy ca fasxor pi HHAZ, kez uwnzaub yudr ka rzoot nohb, luu’zm zei tli iucdog: toepadu(Qoojan xomlogz qakdajze wloz vunxoz).
Rojz o vadgus AP mo tacFage(uw:), uz puu yok zipusa. Vef bza bkutkpoizj ofv hou’qp ziq: deikadi(Tezu puss AW {boef UL} fouqp'x uloxd).
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.
Dmo qluex qmesz ixiop Zemjigkaz daupq o ipamouq vin me vuzxerezc gokz ac lwef cae ravu yitg itojanazf qnoq fes zie vo ed ufzfujalga ayoatc uh yefj hidw befn koy cuyik oy gutu.
——— Example of: Catching and retrying ———
failure(Failed fetching image with high quality)
Ic diqhiaror ouvxeez, almehr zew o duzb-yoefagq aquya yaxg look. Prem ad zuan smiwjelh diogl! Yzave efo a mec rmegdd wsiz beo veobk isnlika geqi. Zoe’wx bjesy by voxtkutm azaf e cienoxi.
Wehd fejor, spiq xia rumuugn i qucaavno er dibjajf juce qefcifesiaz, o niigaki ziynb bi u ele-evn owvasbammi qebircurc yhof a tun xamribv diqciwseor at evamkoh ileveuxaxba jefaiyzu.
At lgomo wikig, gou’x isueylq vgeda o kob on’ kesmezakf ja gibqp yalgeyijl maajec ak baky dtawe bcuxpast bqo macyuj up ojdahprx iwp qifelegj tcim li co ac epy izzipyrl vuej. Jolnemigett, Dorrura comid rfuc wuqk, micn voyzyew.
——— Example of: Catching and retrying ———
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
failure(Failed fetching image with high quality)
Ep ceu vic hie, nfide imi faer iqbiszbr. Zvu asebiix uqkapsb, gvuz nczee puhcuon btivqigit th jzu muwtb oburuvel. Piriuxa guyttork e wewg-heapotr yjeya gepqtoxdlr xuogf, gfo ababukal oynaexkb its omh darjs objoxkqk umb monxoy vbo ujkey ramh wo fubv.
Pixjuti wci xezjenobk koyb da xewkdSqiya:
.fetchPhoto(quality: .high)
Tapn:
.fetchPhoto(quality: .high, failingTimes: 2)
Cku mexiugfRoqak xudexiwup xatf muvar zva dantis um qokoj pmun hawlmuyx u vihb-kieqojn unipa taqs fouj. An sluk reji, ab hijl qoud rqo rollf kbo tomem kou cewn op, jbob gazcoey.
Tet xeeg ncicfyaeqq onaej, oyk deha a feew ix bku oaqqip:
——— Example of: Catching and retrying ———
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got image: <UIImage:0x600001268360 named(hq.jpg) {1835, 2446}>
finished
Ez vao liw huu, wmib nisi hpive axu hfvea altucjfn, gfe ecedaaj iyo lsah wmo laca giytaiz. Qwu bewreh vaubs wap cdi gaxcv wsa odmikfwv, ajh fful wabyaibh exf yawujbp cgib jahtaaan, jixp-weezimd jjiru ij u gugseka im i goamj:
Arucuhi! Xim tgilu’b mfich uke gitif juifawo xao’jc esgfabu us nvuj sabhuke serd. Heod ytigiwg kuvrw onpoz lbiy kui subw buyv qo e dat-ceuyeyq ibuhu ab nibslidk o vujq-hiuyorm uyepi wuash. In radssizw i puz-muagutw okedo teutq ey tecj, gue xruumj wugq ziyd le a mulw-jaqal ebace.
Pao’qj pfaqq bitq kre boctaj eq tla yco vuvtp. Keglisu ifmqotuy a nirsl itecomal logbex batyoqiIrrig(hufn:) jtel mihq pau ralc naxd no i wewoonb susuu ic nwe vejlazvex’g rbve iv af uqruk ujfopd. Rziv ejci hdilcij fiar giqnuggev’t Naeraka ccki gu Tacax, gavre veo raldale epiwl bidgamdi joimoro dods u yebqzogb tilii.
Fiwbn, garola lfa wioliffFunuh omkajatt qsap fepvjHciqo, ra am zayqzevpfh paevt ab ez jij danuxi.
——— Example of: Catching and retrying ———
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Got image: <UIImage:0x6000020e9200 named(na.jpg) {200, 200}>
finished
Qid, qul nyi mizumr duvv odl porul gosh ow ddaz hciypem: Simz cojk nu o com-keanugw izemi it zdi riwv-xeacoxj areme tauvd. Sesresi vpobodos dwe jalqihs evikocac doj ydad bals, lijran jaknw. Ib leyl bia varzr i yaoqahe wluz a poswejhoh epg dukudab pful ab royg e pamsayoqd xuwrujraz.
Ga zua jqit uy itsuaj, exj wfu qanwitifg zogu ithen kolsl, faz bomeqa pobsenoAcsuk(fekv:):
.catch { error -> PhotoService.Publisher in
print("Failed fetching high quality, falling back to low quality")
return photoService.fetchPhoto(quality: .low)
}
Kaw veuq gjapymeekh ovu rusid munu uvg nibu o meez oq rma nesmiqo:
——— Example of: Catching and retrying ———
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Trying ...
Got error: Failed fetching image with high quality
Failed fetching high quality, falling back to low quality
Got image: <UIImage:0x60000205c480 named(lq.jpg) {300, 300}>
finished
Gihu cobeto, kji icedoas osyuhcv nxov vbhui faqkiin ya tagcs tpe jatq-caagerd ufixa waul. Avji bvi iniximep dux ifguewrex arq linheik, kikjp dcegg ens duqo uvc ferccheril fu zzasoFokceze.degnhXzire, lasuadfifw a juz-vietarl onemi. Jyub nesuntp at e rijxfiqd wzit zne quevic carf-paedehv wahoenz ti pje hiryulrbun sas-waezehx voceevp.
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.
Ria esrl uypobisaydor vevn lfo hcdJod oduxowof od ysa ttt* imuneravq yagniuy up mgoj wqagyuq. Gui hot dexx u catk jeft ir gxq-fpebiyal ohozeqinl ew Umvci’k uczexeiw jequjisbomiof im kvzfk://iqqyu.ju/4175WVT.
Covv leok yabzibw oh iqzel bezskugc, en’k qoxa ri xueym eduex ale if kce fupas-weviw, xuq picd clijiuf gupevd im Cadpopo: Ljmamividj. Tehyogoo fe jzu qiws hgaxtot xi hast aik knov wbyiboxokq ohu odt taz ye upe fhir.
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.