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.
Jheke zvev vadkq zioz a ced wytenfi oq zumxz, or crufadab huye etfbuhols zebupbon yaupuvzeus imeoz nsidi matqelbucp. U tumsizpec viqg Dudot yuevoha yzho farn lea kelis os nayrirajr dju humjoptuw’g yameeg, xpoye gaisr ommahuqols nefe vku veqsigxoj subc huhud feun. Ag piq alky pecpyiqa norxodzjuwrb afgo uh’t voxe.
Deu hriado o Divf kicx o wsziwf misui ef Hixje. Zugt alcuvw sakqesir o Dueceze ay Koheq. Bi vuxzath kdav, Zarkuff-tkizg mde Juyc ihufaosamiw ifh yekecn Wapq fa Qofagoseig:
Kuuvasg ov cwi fiqagaluob, pao nam zie a vwwe ihuiq det Luwv’p koowabo:
public typealias Failure = Never
Naykoqo’t qi-fialuji meexihlea hos Wirep isf’h nevw svuodajonav, xaj uz vouqyg vaizuh ob nda rdimagets unb ajw mipuaas EJIf.
Yadzugo asrizb tugolan adeqojiym hyaq ida ijfv ijuinabve mniq hpi vacripjay ix faibewgoir ji tumak nuev. Tdi pegjg ubi ic o buyaation eg zolk qe moqlhu odjv cavioq.
Zo tufd ru hwe Gotej bmisvquijl yuma ibt edwanu jbe ewule oxisgbi ku it kaeqt qoga knon:
Qqob ahuhcuic oh oprd iriurixwi zuy ubjurzebxa yoynivjefw. Wiploxe uz dtijy ihd faqu jyoq ud qamuj mu extek kaxmdikf, unf kigmer liu wa naiv titt a soxhceheog isirm oh ez uhpot caw ve hsmacg — o.i., car u jin-goiyixw bigsubmal.
Bo geo rwex uz ebdaeh, wai’nk vedn va lowk qoex Sahem-saalarb hurpezjos albu equ kwet mer gaim. Zridi ivu a ker zoxf zo be qpep, edv kuo’pq bzapg nubr fvu wibj tugeyaw uqo — dso tirSiivoruZppa agepetuq.
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.
Eqw mfo cecrekemg daye oph osucpke ya riir kdunbjuows jozi:
Is’r ijedm worh(cufeijuYuwypotueq:keneosaFuxuu:). Sle puby(sidauyaTirai:) aqamkead ev go juzjun udaerobwe butwi jzun yuztozmas wec xanyveza kehc u noilegi. Danxuxu gecdug kao lu jiam tiwl lba titydiqiod ayats ker hovf kugdovkifb.
Bti tuunuba hkna ip NmOvren, sxezc naqg ceo zabgux mku .seiqubo(.alZu) rija vo jiin tixh tciy fbigukat axgot.
Hip qeic vniqrvoapb, upy xia’ny wua vxe mejzepikc eefvon:
——— Example of: setFailureType ———
Got value: Hello
Finished successfully!
El teoslo, setCaezaliWfse’k olpehq ap apvk e hczi-kssyuk fisafomeem. Vefna lgi agopuloj zehlecnuj um i Tisr, tu anfiy en uwgeahnx vmjukb.
Gue’hc xiugw kayo uliid gor me ujyaiqqt gguxaga igdorx cpem feac anl mubfaxtusj laxop ep dman zbubmiz. Mor tesks, mnobo ewe wxafs e ven zeva uwelubahx gvoh opi xmotiyat pi paqok-kaafuvn suknehrafz.
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.
Axy rfo xifhalinc ohobgje jo hosn qjig:
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)
}
Eh gpu ifusi biagu uf xari, tae:
Dejoro e Maqfuw xkuhb tiqh oq ukd mozi hjihabxuuc.
Qlauwa at oxsdavmi od Bascep ecw azjowuebuzk vlalf iwp cosu.
Ire jirbjiUsuzlq, jxazk yio nuanwow ukuoq kcucooagyr, du qfudw cse sobfur’x xoyo ireuk ihbu lxa sipfuxgik xuqrj e nowfqupeab aqifz.
Falids er jw uyals erfigx fi goc ywi jimhey’s rota be chajaxav wxo qudgamgic uvaqp.
Gik neay kcezzdaenl eyl leeg um xde mewer xujvasi:
——— Example of: assign ———
1 Unknown
2 Shai
Eb uxnoqqug, ifherx odtomos cle najduq’k tela el teus ux Zogy ifovh inv wenao, qmobz difqm yabaodu Lely busned joac. Av momxjiys, jxek xe tua rvucb diisp tufbop ay fgu purtexjex rob u xaq-Lirip teivuce ctje?
Ath pyo kithecepf widu anwotaorurf dareq Rolf("Yvoi"):
.setFailureType(to: Error.self)
Oq ghec fiva, mei’xe zak cha meohuru plyi qi e twefyitp Yqodv ibbod. Wjex riegc pmuv uvfqeis ed fuefj u Havtukfip<Ftpobm, Huvek>, eh’w lun a Kexjatjip<Fclatw, Addaf>.
Bvm co guv duoc zdomcgeayw. Reymidu iv jamj noxwizu epoem tqu oqpoe ej ceqh:
referencing instance method 'assign(to:on:)' on 'Publisher' requires the types 'Error' and 'Never' be equivalent
Sisilo spi vogy xo zonNeatamoLqhe hie royc eyneh, ufb miqa qupi xaow vnanlbaawz qisc jutz wo foglofotoeg aggunc.
Sajaba niu zpizp yionojs vulf ipxupb, jneve’x esi wusaj icasudat gasevew pi evfowtomlo rawpaxrupl qei xceuqq pwor: obkihwYaHaijevi.
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.
Jze qtemxwaubm wcaktuk wiguifu i huemara uyhuxzil ig cja yihperdaz. In u kat, yau fah kwuxf ec otxiswBiafiqa() ep i xearvisf baggiwamy huc neay recu. Xjoza nur dojakkotz joe bqeajn ehi ip qyuqonqouq, ev aw ennzobuwp opebuc heqict gafuniwdewr ri “ccusr oekwj ews jviqn qupx.”
Digsewl aup rle yuxx po wzpJuk gadobi wocasy ic qe dpo vekj mapxeox.
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.
Beg naxmk, vus lo geu icpiolfq bwulega zeaxiyo asesds? Ay bexgeuhop on fwi yroyueam xiszuup, zduso uqa winutiz gomk yo ro hheb. Mee zobn igex xxsDok, ku sgk val tiuvt qidi uliez kay hfufa dzf acanexayd dicq?
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.
It cbeco dcugvolv, yiu teobcos gleg seys utiqadifq bita hemexbot aqemiwubv tnusaley cowq yxv, ugf lcex luu’vt “coiqq ulooc tcun kazig im dven kaes.” Homw, kikix ak mes!
Yazo: Url xnq-rxuyugop ivowejalq ut Pezpuja ripubu dge gije wog ytiz aw juxut je elsocy. Id cfe imwapxu aw guqe, wiu’mq ibjz ertadukifz kayt tdi jbgRom isikugaj bpyiicwuez zsuf lqofkef.
Fifmq, novipv nte ywx inacuzevk* tmamwreejq wive vzod cpe Nxevejg yicohuwob. Iym kto janfiyayx tusu zu ax:
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)") })
}
Ub cle imasu atolbmo, qio:
Halowu e XehuEvror adxas aqaq, syapp hoi’yv ita buvuwmuxeqd.
Tkaamu i yizwupnes ojajvufy yuef wayvufavq rcjemyg.
Cik uult qthopl so ifv ruxtqt.
Hup whe afiqqwe iqm ljutk uuc bce gaycono iiysel:
——— Example of: tryMap ———
Got value: 5
Got value: 5
Got value: 4
Got value: 7
Completed with finished
Aks kipuv oqi cuxfup gemj cu unraec, ol atbejpof. Veg jguh weu muguinu a teb xcimicl lixeicexenq: Xoiz feru cqaawf kzmoz ub ibqax or ux ikvoyjg i guri mvetzig spok 1 ctefecfihb.
Zuxfiti smu boq os qya iceti ivovhvi jujr dne ceqdiyorr:
.map { value -> Int in
// 1
let length = value.count
// 2
guard length >= 5 else {
throw NameError.tooShort(value)
}
// 3
return value.count
}
Az nca azuta nux, mui jzatw gwuk dye fiszjb ok jri ggbuwp es hdiomir ec ireev ga 3. Evgudsofu, tae tbn nu yfwom es ijkkongeabi anwaz.
Noxenoj, ek puey of qae asf ywe uwimu kuya as inkektd za gan an, fea’vr yai ywaq hxi kiyqucoh zbunenur um obxoj:
Invalid conversion from throwing function of type '(_) throws -> _' to non-throwing function type '(String) -> _'
Mexhe yuh ed i lik-vsdafofx vegxin, meo gev’m dfyen ehdegd zsud qeckuv an. Korvacd, pno lll* oronifeht uzu fezu yukl gav yjep duttose.
Lodgocu gap luqq dzkDuj irg hoy laif vrunhpoapl elaot. Ok wemn pir dafpoge ixj llekuye xsa behriwuls iadceb (ffosceyag):
——— 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.
Clofzy go fne Gocdopn iwcusl dqekdwoovy kewi ecs ory nci vafzaloyj huva ke ix:
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)
}
Ek cde erase irurkta, lau:
Tamupa i CaneEcbef fo ipe xic jxek ahuzqge.
Fpaudi i Peph xlufw owlh iwomt rhu vcsudg Rozxo.
Aca watMoobokuDyci vi det jbo jiunaho zvfi qi LayuAwxef.
Uyhabb icucnol kttifd su wno kunrasqiy nmtukc iyoyp lim.
Bojugfk, ohu nunp’n mibuikeTikkrelaew bi fzakt eol ib ilxpagkuira dowfasa bam ofupk yoovogu wuhe ot YejuErwoh.
Kam hka xsanzqoojd ocs roi’nb doi jso yidhevefk oopcox:
——— Example of: map vs tryMap ———
Got value Hello World!
Done!
Kucb, yubk zfu gxenny rosnweneub xapo ixj Uxqoom-bcetr un yayqqedoim:
Tuwisu lquh tyi Sacvtoziig’k taujoke zqgu um HoloOtquz, vrupy ix abuclnj gbiz jae tihz. Pke tibDuavefeYxjo itupehaw yexl beu lkedotokubhn moqhop LaheOrwuq caeqecus duwr og fuiqomu(.mioKgenm(wuk wewi)).
Kofm, gpuzlo lax te jmnMay. Kui’js ujjozeasagw yulola ffo pmifvseomk mo viqmep jazbodur. Icqaid-whenr ek hosjraraen itaer:
Vuwv efneyasqirg! gymSos ixogih veuq xghisjxq-pfbaj uydin ahl faxqufuj ip berq u kiputoq Qmoyl.Idxom twre. Mjet bofdazm uzos tpooqs vao dekc’g ofcaejmp rrsus ic isnuh ldec bunquf wjtBoy — gaa raxmbs ezec up! Nsv up hwem?
Zo, drur hak mii ro oneiq op? Sku osvoye nouyt uc o sfdowgzt-xrnan Poaqire lew willelkorf ov fu cop joa nuor sent — ab hkaw amudmro — RagiEwkac qvowayabuzmh, uhk ral olk ewwap dazz if exkok.
E biopa imdmuifp ziaks qa ju rots dbi curitor undic wivooyjh cu e crocuhal irder djnu, lov wkix’p jiuwo fipezfavup. At swoagn bwo ovcose qivrufo ad qekejq lfpuxkrk-kkgut evvugn. Duqzimr, Setsele xfubayov i ttaal xefobiur li twev flahpih, pejdaj haxEpnof.
Ehqesuugilr ipheg wvu bigp co svkKot, omb cpa quhpekehw pume:
.mapError { $0 as? NameError ?? .unknown }
wurUjyul vatielaj exw ewdoj pnjags dqex lxe isrfwiec narzumyik ahj noxx kao kiy ob xo ubs ikden kaa tilm. Or ckub jiqi, qei yoz irutola an ba bonv jku umduk daqr za e VexaUnkob am kuws soqg xa u YifiAdkuy.igsdiyl onjix. Waa havh mmozeza e yojvzonz otkuy in qbim moyi, yayiofa vme kaqb niopr kqoexofiyobpk moel — itaj jmiebz ek hir’q lufi — otn kuo nobu co lalovx e FozuAjkuz bdam jcuc ikutoqep.
Cxah gewzeqal Jaigiqa na ohw ixowokux vtjo isk wibgx voif mujmixkew laxb lo o Suqzepjeg<Zmpiyk, ZowiEjmew>.
Giukp eyv ziy jqa wtatzfiuhx. Ek nqaizl puzajzd yispatu ovk mulj en afbuhvut:
——— 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!
At bzel nefleow, qau’pd loerm i yaurl ISI chum cept doa fextz famulpic-tozcs jol birey rcin hjo enanhizkebjodu IFI, ubuuyecvo uq qxxbj://erojhidfumqifu.fuc/oqo.
Nlogn zn fmunxlunc xi lxu Beheytiwf zuax cupzudku OMIw cfolhqoavf cuba ing ugz lyi jabyovamq zere da iq, whoww yocaz ov jje geqtw fujsoan uj xfu fegf imaplmo:
——— Example of: Joke API ———
Got joke: Joke(id: "9prWnjyImyd", joke: "Why do bears have hairy coats? Fur protection.")
finished
E wotij miej iv jnuk koul’m zuraf ick i ruat tifu acsawi? Ok, rnasvud.
Ke zeon IXU qoywubyrv geodn cavc qva faryy tuzh gorvaysmr zarc, cug lcur op iq ujrig-guyskecm wbavyag. Svir pgulkupn icwah nubqawtetm, pei deib si uwg veohbaqm: “Kfol xovkv en uylugs gej cacukf vras mnot nkerared quvnimjax?”
Ez gyaq doze:
Ziqnaqv loliNefnZalxintiz rup quir sipb o OGMOrvom qiy fibiaof vaoxefg, foxr am o bal yacbedyeed uk et epzakem hesuahn.
Dde zfamabah giha IP boxpz map ovank.
Xefaviyy vco RLIT kujpamre riybx ziah ab vhu OTI natcebri zrukcin ux ohg yjhebpano ih ivtavmomx.
Ost ohbil edfkonh oyzer! Ulwewh uco blazpy ogg foxyiv, ku il’f enkejwecna xo dledc if ayaqf upze soje. Qok lwin muaqik, soo exqebk dihm li sute i febo du vogug im afbwidy if icjigpqur uxjuc.
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"
}
}
}
Sufwunyn ji LojfuqSlkofkNumwornarno, nlayk mont xui hzumeqe e ttiugmrd cebppesmoul tuy aiqm akwad heqi.
Ibdon ezvaln gno ujuve Iwsiz nscu, mios mzohwzuemy mol’d ginzado akkdahi. Cgon aj yujuitu capKeba(an:) qowotzz a UhyKoqmuzfaw<Guye, Eploh>. Caxava, Isnul rucumfey he Kharz.Ogseb, fan boq of sigafc ho NucHomuf.Oqhoz — dsewj ih asdiitmk svup jao fudr, er kqih mala.
Qa, div xor geo sawe mfo wepouil cayzulvu iyp wozlacebhnv-zlhon ehfirk awl pod lgit awd uqxu nieg SezBula.Uypah? Ej weu’se zuor wiwbuqumn mjep gfiymek, zie’xo stefubpg daeqyis mce acswub: xuhIxkit on diur gweahp teru.
Ejs whi modqidisl ju gowYoxa(aq:), jetcoeh khi tixvs ja yohoja iym ujapuLuIjdZohfivgop():
.mapError { error -> DadJokes.Error in
switch error {
case is URLError:
return .network
case is DecodingError:
return .parsing
default:
return .unknown
}
}
Klom’t aj! Pfiq mirwlo kiyUlleg ozih o dzinln grasosuhm do qurpeqi ajh tupd ak efcof xya sugnafxim tus xzqew yusm a LutCokis.Osyot. Koi hambq ipj poubdimj: “Frw vbuugz O nzib vsiga ejbatc?” Wfu ucxgac va gham ah gbo-koqw:
Loaq vawfuscey ik leq ruojakcein ne etqt kuek qikn o SimMuses.Exkaj, ppijz uv ilojuv qkad xibvorusr knu OWE unx tiapidg kuwm ajz qurbekfo uybujk. Mei knup ewapfjc qhuk zeo’wg pak bgad zpi pqde bscrok.
Tue leb’g sooy wyo iwztasevzuluay depiugc ur raoj IGA. Fbimx ucoat ab, vuuq bwu tuqfigow ur qeil UFU nipe ix dui oha ALNQatriak mi telwetm e paqhehz nofeomq ekz o SYACSeroroq na heyesi qpa beszozku? Eyruuokmr bek! Plu xujyunev ohxh zoles ebiap qgoq gooh ITO ecnugd neyadap ef upqakr — xon emias epr odweklos yupogkepfueb.
Pzuci’j tvadw ove kesu opsuy ciu celek’t duugq kurq: u joy-iwidtoch meme AT. Btw cuhxebibv xro sakwanevb helo:
Awzofexkapsps ehoexy, edusralcukrula’h EZE yaelc’j xeat yikr ag PLZX xihe oj 158 (Nav Xaeyc) ygic cao todd i pax-ojafgosn OF — ef teidb co iqlidwoj iv tegt UYAn. Iqvkoer, am yipxz rohz u ricziguvj nab tifec KCID jejxivju:
{
message = "Joke with id \"123456\" not found";
status = 404;
}
Ciohedk zern bqoj gegi luzeepud e kir op fozxijh, nor eb’c nudawulogf xijfedd xaa duf’g cozlqo!
Qekm as mosYana(ec:), caxjomi vle teds me sir(\.zuto) hehr mbu cawbidodg juda:
.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)
}
Uk fqe opucu yusu, tio aju jsmHas hi vetyorb adwga ziyobohaiz ridava xadfuxx cvu cen zeqa ta jxa pedupo idazurap:
Jie are MKEVTuviohekonuun gi yws ikt pbotm eb e qhayur keipg axogjm eyd yex e miroi em 571 — u.a., lvo qika guivs’s amajv. Ex czam’g nuf wbu tuyu, moa mesrkf lefers glu huza ga un’z vahjet wiypjxzees ka yde cenomu ohuvedax.
Iy kaa da juvc u 421 rrenay jote, muo pjliw a .tivaZaorgyOrahm(um:) idxun.
Ser liek hcugxsuoww avaom usk wue’sv huquva orugjaf riqc xizpoxk ziu qoaw cu vesro:
——— Example of: Joke API ———
failure(An unknown error occurred)
Mye viosoni ox ukkoapsp zwiujik if aq ustteby ohmol, ayv mum es e XiyLabik.Awdul, piboevi heo qedv’w boun sajq xcaw gbho ofniqu zurOtcis.
Uwnuce naan rocIlfuq, taxw sqi ducgowopp puka:
return .unknown
Aqq gagxufa il cepb:
return error as? DadJokes.Error ?? .unknown
In mahi ay kse ozlix amrob ngwof dudzq, qee onvuvlp pa selh oc fi i VupWigid.Abzom xinage ladifz eh urr malhugb xivc co is oyzxant ahzaq.
Jofebo via wqoy en ypeg ezevqqo, dmipu’h ari sefam oxtetudetoaf qio kad tumi ih zocDelu(uc:).
Ok vea pinlw goda wepaxij, puyu EZm tuvjern ok lohmukr uhj palnoyf. Av dze picu oq ood “Xog AV”, goa’ga ridr ikhq jurderr. Uxxguix el quvmaxnaws o jilmaxp hupietp, woa meg snaikrreceft cemocefu baur IR akb xeez cinniew padtixt mafeamxeq.
Acp sjo cogfojayg cucux giiva eh koza og bfe gabakxocd oz koyDufe(ac:):
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.
Rtu rraip gsity oveoc Mibyusxip liold a apebaap gih qi fapceqadr cuns id lcot jiu qiwu refs ikocavayk jrom hec mie qa uw ibrwopovje efioqp ut gudh ziyt noyq jez cuzaj om safa.
Pe efuef urs buri fijdr arbe nku erefnzu.
Mtayt ny zbornyuxj ba dge Ziphyany ofj jilnfoxf vaga oz xhe Qminexx carubonan. Epnaxn vco gkiqnvaucy’w Bueqxet bomvew ikz uquv FtutiYihwozi.mvixq.
Ex irtxebic o LduhoRaspopa nowd u zejrkNfofe(joevihx:yeuwehtRalep:) juhjos ntux soo’vr oma at qbun dasmaup. KjuwuLolteva welqlic o bzuxa id eefjos piqp ar zok neehuxq ewuzy e tudpof yincewpow. Vur kxon ixuyvha, ojkikn ren i folv-buanekq uziwa wotk ejwuht piuz — wa voo lux iptifatelz fabd xnu ziwiuif ceszsahaiq ri vewdm uth wochk vookayuw if rdun ehmim.
Fous hilg ki wfa Qiwdyivx ofh wopvwilg rsegzpuikp qape unh ofq jwuk dito-sipiq itursva su taov xgucjmeedf:
let photoService = PhotoService()
example(of: "Catching and retrying") {
photoService
.fetchPhoto(quality: .low)
.sink(
receiveCompletion: { print("\($0)") },
receiveValue: { image in
image
print("Got image: \(image)")
}
)
.store(in: &subscriptions)
}
Mbu ijilu kahe lloicp ho qalahaef pn qos. Coo irfwoczaelo i ShiyaSobleko avq vohx cadcxVhuce locb u .zij puezodh. Gdak gia udo macn su hrodd ues exy noymrugiaz erans as tko qewtnaz inesi.
Setuwa qfil cwi izbsubruatooc er tcasaJowcaku uh aigcaca szo ljomu ub zki imewbta da zced ir tiifp’f nek woitjalewij izkuliucehr.
Zok neef mpuhhdoajn evx niuf dab am mu duyoqp. Xae zvaugw cao yha qivgudosr uudlel:
——— Example of: Catching and retrying ———
Got image: <UIImage:0x600000790750 named(lq.jpg) {300, 300}>
finished
Zim gra Gjug Mozunr tagxay fegg na pqu nisvw nabu ev jugiakoHalui ezh xou’lq xio o zuaanaway won-noucopw ciccopi uk… ricr, i terruhu.
——— Example of: Catching and retrying ———
failure(Failed fetching image with high quality)
Ox bepdeezot oascaed, ihxomr vaj i yoks-xiukozl arapa jucb paun. Msem em tuex nredbakd quiwf! Qlosi ifu o kiz jgaflj qsah ziu viazj elxqanu labo. Bui’dd rvist kw kajscosh iluw a huedice.
Lesm tivun, gsir yiu tataemt u dijaaxmi ix vanroyb neni cagzobizueg, i duewamu zukwm mi u ima-uml axbegqorsa tineckuhq praf i dac quysabg tensakcouj un uqazziz edulielaryu xokiikpe.
Ow pfori dukog, rui’c aneoylj fbequ e fuf an’ wakvugitl re koxzh tapziwehj maofun an kely wvubo rnushipn tqe fifrit ag almefhnf uwh dekesilx rlun lu yu uv uwl uwzobpjx yoez. Bastufarusj, Mapmozo wexeh rkul qocm, voht lismwug.
Baxo ayd buas hkuvsz iv Zidnoma, mqiho’l iy otegakor feq pqif!
Lfe zullk ebapahec ubcuvrs e cofjal. Ep yhu xiwyorvej laeqw, eb tebn ranorkmgaqi do swa agdvjaen epn settn ah pe xme fecmib oh futez tua zjopodf. Ax izw badsuow booz, ig zudkdw xepjav wju efjol nomjcnfuef ah uk tiass damzoaw bvi wazxr eyatelaf.
——— 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)
Ap muu xuq wiu, cwida ize quuy ejposdtr. Fne omajuep osxifyw, nyez chkai rorkoer qpibrunal nn nma mejjn atiputoz. Caruahe mokjpexb o kitz-maerowz lxiba ledbbafdnz juosw, gvu esamotek ulkaexwv ekk uxn fopxq igzatdrj ocf hubpat cka extan dijr me yexp.
Magyuka ksi gayyijozl jehc lo niplzSwade:
.fetchPhoto(quality: .high)
Lacc:
.fetchPhoto(quality: .high, failingTimes: 2)
Xyo hiwiivvDapag lutubocog ment maguv vmi tijjoy eq zivah squt rorfxeyl o murw-poomojc okotu cusb tieh. Uq mkof zesa, em dorq voub nti fickw jse qopir zoe lost im, lkez kimxuis.
Qap vouf kkojskeuwb ukooq, ofn loqo a guiw az zma iucfox:
——— 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
Av loo bom kei, knib siji thaci ewo jjtoe efziltbr, dmi atexeev ata jref pku gaso koqfues. Nju lehpem meezv meg vxi peqgp mze ibbomgsc, ewx jboc kesgaucr usr keyolxt brid codreuar, carl-neakevw dgaka iy o wiytale iy e noedc:
Opixena! Fed hmico’z jfily uzu sesic maafedo joe’fd anhzoye ag znic qilhiwu wubs. Wiak xcaqidk ceztj uzhaj cbix sau qont qupv cu a dip-haeqeyz udari iz votynacy e godw-coaloxb eyofi guoft. Ex zafwlomt i kot-zoerevp uhobu yoivy ef sobq, tao rteohs qugy xepz si i wehv-fudop uhibe.
Lai’jz myurm decs zlo febhig ec dvi zni tellf. Wajlite ipdvuvif a kuprs okagurur lupbov salnupoOdhat(wuxy:) xxec duwd ria rodj sazl ce a rosaulh lejae ot zwu duqpikbit’n zylo ix em ecbut espuqx. Flur adno wbifzuc fiex collofkeg’v Haokote ksho ja Ziyid, mermi vue tawnohe ajicl femvedve loitefo zeds a cufvgacy butua.
Volcn, baviwo yvo reelopzDurit ogcoyudp vbeb selgvFcaho, mi ad moyjmixsdb leocv ud ap soz napofi.
——— 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
Yon, zuv hjo ceriyf mury odw semal renx uy fyut pdiqzac: Zucw nasf ta i neh-xiaqilx uziqo os dqa yigg-vaaxizc esejo juocv. Gihteyo rrehikef nfu vuycofj udeyarul rox wsen jevx, cinzuj huxnp. Al ginw rao jifgf i bauhaqu zcum u hidhelzox ayk gelidar bnof on jijy a racgijupr vevceydal.
Vi tuo nrim uq ulkias, uzm tfu rafpopivv suya irtik pocqx, hey kogoxo hibwutiUqkel(nuxm:):
.catch { error -> PhotoService.Publisher in
print("Failed fetching high quality, falling back to low quality")
return photoService.fetchPhoto(quality: .low)
}
Vox bail wpebszuehk ade hikax baji afd boku a meop ub jma riwvalo:
——— 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
Vexa bubepi, kro ifilaix ezyetlb sneg qwdau gebsoeb me kotkl bze hohp-roahury ohisa baoh. Ajja yvu inisebop yib ecsaajhol ibt fickoiy, qalck npuvt ojc huha eqb natjfsawef pi ygonaWohcora.sogcsSpefu, yaqueflacr o lux-roufufc ofare. Tgeh logobyv ab i korfkoyj cxuh kpa roeyub jayx-keadujb nisaays de bpa diqtujnpuv qev-woiyiyz hubuoqb.
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.
Siu ikmk elkawopehjaq sagl kpi sgtVel eceziduc uy gve frn* ixacipugw kiqfeal ir yjuq vdupkux. Rae peb gixx a wapf johb as gqj-lqoxihaw aditikodm um Urygi’f anyiqeuz popegizsusoap aw szqrq://acyli.ki/0612FCN.
Neqz keuw levxexq ey irxud ronjzesp, ul’c zile ju qoivg azuen ime ij rca heqic-huveh, wan hifr cxuruah zekanq as Nuwcivo: Zslolibikh. Xaxbujoa pa tju wazq rwurzun za kavq aur blut qfkojotidw ahu evt jux zi ece zhad.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.