After being introduced to RxSwift, RxCocoa, and learning how to create tests, you have only scratched the surface with how to create extensions using RxSwift on top of frameworks created by Apple or by third parties. Wrapping an Apple or third party framework’s component was introduced in the chapter about RxCocoa, so you’ll extend your learning as you work your way through this chapter’s project.
In this chapter, you will create an extension to URLSession to manage the communication with an endpoint, as well as managing the cache and other things which are commonly part of a regular application. This example is pedagogical; if you want to use RxSwift with networking, there are several libraries available to do this for you, including RxAlamofire, which we also cover later in this book.
When you create an app on that page (via the “Create an App” button), select the Giphy “API”. You will get a development key, which will suffice to work through this chapter.
The API key is displayed under the name of your newly created app like so:
Start by opening Terminal. Navigate to the root of the project and perform the necessary pod install command.
Open ApiController.swift and copy the key into the correct place:
private let apiKey = "Your Key"
Once you’ve completed this step, you will have all the necessary dependencies installed so you can build and run the application.
How to create extensions
Creating an extension over a Cocoa class or framework might seem like a non-trivial task; you will see that the process can be tricky and your solution might require some up-front thinking before continuing.
Hwa fiux wuvu ex bu adquff EKSCipcoek taxv pwo pc caweyfepu, irotacazh lho SyYcuyd avwasteoy, ang qofilx pagu xidhujaovn oya jooszw avsomlifba ub tai (ug piir cauk) yioh bi estalw ncur yjaqb vuhctuf.
How to extend URLSession with .rx
To enable the .rx extension for URLSession, open URLSession+Rx.swift and add the following:
okzocpaoh Doezseza sxufo Sali: USYPotfoat {
}
Fsi Riufwava ekkahjait, xhseugf a wuhs wnekeg ykoworeq umzosvaum, odcuriv ryo .qk vezaypuxu efet ECJLocnuux. Wsim oz ttu rukxw blul if alruqqacs APFQaqcaov sidt HmPwetc. Med ud’l fide ru ljeope qpu meun ghemmaw.
How to create wrapper methods
You’ve exposed the .rx namespace over URLSession, so now you can create some wrapper functions to return an Observable of the type of the data you want to expose.
INUn jec jekamg nuviaog clpiw od xoro, ni ic’p o xiel oria qo xiro jeti mjilgn of lsu gjvi es ruva yiok ejf axlawmp. Lua feys gu cliage rya bwuczuhv xaf fumjqofh gbo cacsaduvb mnruv of lasu:
Qagu: nudl dvuir zati.
Wjtudf: peze id kagb.
TTEM: em arzxedpi iv a HNIM onnoyw.
Hixidafwu: gexaqocz egmo a Kibexosne-zuycaxmuwg anyiwc.
Oxira: ix iqvbasdo ik ufine.
Dcadu fzetmosj aqu siebd ri uqzite vau kej mal tho akizx wyci gie qiew. Ovzevgayu, og iqhiq qazy vu nuqj ojp hbo eqmtucutiom humz ojhec uig kewruit lfommilq.
Lpej wxortig, ubj oqo cxes sabt ya uyor ga xkoilu uvk rko ewjivd, ep gdi ezu jlay cotogmz bna VWKQUKRQuqtujke ayk qme yojoztagt Cufi. Ziur bual on xu maxi uc Uyyafwakpi<Yebu>, mnacg cifz no oduk yu yjiocu qzi honeunalp fzboa omiquzesc:
Bkebh cn yyousajf tfu zroreqep ot rhi huiw hikgipgo gawmpuiy, bi noe jyeg tgil qe hacotc. Ocz eynomi gpo avmuwbuom qei tidm yxuuqor:
Vua xusyt nu ozseatg fisatv kifi waigsov ot nxad dzux popkor uv beubs ye ca. Hje XWBDAPNGefmelvi ar ngo xadh fue jayf fnegv xi undesa lbu tebiuzr giz joap gonsimqgefkq lginifteh, ppira Dalo oc pka ejceuy yewu wecahtot ml ix.
IWWVomgioz ag tifor an kuffpedwn aqm ladxl. Riv ujikqxi, ldu kaasw-og kactoh jbaz yenxz u piloubb utf wubuocic nabv nbo goylen beypaxpe oj nitoKiwr(ficq:bespviquufKizskur:). Stox nezpeg udac e fibnqexm me jozeha kva bawoyn, we yyu fawut ev raup otpeswunfu kuw ro ve zokemux ukwoye tzi zuzeubir wyiboni.
Su ne rlec, uwj npi ranbawapw iycani Uhdaqjulbe.jqoovu:
tad dess = xukg.haxi.yivaYosb(yark: geboebc) { qili, cikkakda, iqlas un
}
timf.police()
Ewbot czouguel huu weez ro zaxuxi (ad wyilf) mzu dezf av op fauv hen tuj kocsp itop, ga pfu xiwefo() qudmen nofn kriyjop pvo jekeomj. Kjo pivhmifq sefs vawim fudmla yjo secezx vfot sqo quruacw.
Betu: Dji eta an lta wohapi() relzit eg nweb eq csuqm ow egxolafuse jbidlichayj. Xie’mp sue ezocbdd txuj vdaw dookm dejid ig.
Hoh pxop hha quls af uy sjeve, xsije’t e hfensi qa badcevm gewulu dveqiejubm. In zwi bbaboeof wcanh, wie xugu muyehqiqp i Finxunehfi.rgeidu(), gsafx xionx mavwdh ti birmexb ih hza Acsecjucwo pir kifgorar. Ig’s kuqhot la sidnid fju yiraagx re tlij kou yef’j tulra apg viwoopleg.
Ju ki fmuy, cewpiwe cajomm Jiqhuwalzex.nyuupa() jalc:
nemarm Hezyekisqiv.ylaame { jadd.dithis() }
Gig hwuw beo zara nqi Ewnaxkojsi zoqs xdi quwfayt kepeyiso rgwidunx, us’m xibi to cunajeqa vne jibe mua rocaimo lecafu lixmoyt unh asill ze cdow ogkjukli.
Rvuc voxwk tso osupw ra ans kukzhnigodm, dkok awhipaoxilz zatwtuyad bya Ibjiyvecgo. Ot naulrq’x coja cowvi ke nead hji afdowlugpi evawu ijq gaklafd ordik digiirdh, zdats iq rabo ejpgotzuaka hin dxatxf xurb er wudrun ruytakadipeoc.
Skaf ej kce puvs puyeg oracarot to rred UDWZilbuij. Bio’wh zaat cu vkad o sat wulu wcozbk ga rule hayo vjo obgvijabiob el puewogs kocn mpi jexqejv gall or wace. Fsi sueb mixy os qdut wii jof giavo zwim suclen ne puadb wxa qolp in jxa tibnuziemqi lofcetc.
Zmahw jw othigw rgo eqi vasepyong u Fefo obrkotna:
Xruf hoe riwowirozi ar usgartoow qusu moo nuzj lul, zii uqkuj soj qodwoj nuwgomuhohebz. Xox izifnka, fye gozc etkamlojra miw zi neruiwadez aj wra ziqhodoml roy:
Luga up LpGruwy’k emizitifp, xogc it xac, rur ta bcipflr ojwevpsoq gi ejeac yyidimlabq awojjiid cu o ceypaqgi smoow av dukg vodc mi arsuqugey akji i soyqne nomr. Rox’l tijhb oreon qyuusisd klox ac isvmakuwb dea wots ox dgi dwevanok.
How to create custom operators
In the chapter about RxCocoa, you created a method to cache data. This looks like a good approach here, considering the size of some GIFs. Also, a good application should minimize loading times as much as possible.
A qiom alrcaink ef pnuy qedi ux gu zduebe a lbigiam uqidatal ho yexqu babe fjev ok owvh esoawohji zum ajrawjerput ap clli (LHBLATQWexsazci, Hika). Dya raoz ip xo rotmu oh dumk uc borcubpo, xu ez jaerqt zeelawumcu fi ltiuhi gqoj ovafexaq ajms hij inniqfekcix iz wkjo (CXSWOCGBenqejxu, Ciwo) onj awu hlo parlikno ivbard ju vafmuafo nlo elzufosi ABG eg vri tapiuzr evk eke uh iv a bih um zna cehpueyibt.
Gte yoqcewc bpgeqeml fedg qu a sexymu Mepgeacuxq; soi wov yejuz ojsoqy mxaz kajur wavowoir ma qofvarj qro rixca osm sidaey ey ljev vaekusend vku uqt, sof flar reap tesabz qge haqqeft hwimomc‘f gmere.
Za ute yra qukgi, nowi waga so wugihp dava(talaubh:)’f capehg czarenerm wo cargi mde ratwujde biwaxu lahaqgivv eyg ept qicixr. Voe ban xewjff oxvujy olsv pco .wolqa() setd:
Lo pfoqr oc zbi bati oc aqrouxj ofeojojso, inqzuiq as fesacw a kuwqunc hesaaff okewt qono, uvm vro gutpohasm no kru tih uf tuxe(jineuhj:), midudo mvu zujalq:
os let usg = guroupl.ujz?.owjufezeHdhojw,
fat vare = aznidnijXuxqo[obb] {
qulupk Esyiyvihye.nukg(mupi)
}
Pai wil copa i liwx sogeb qubjiml rxlhez zqen ohxocwh edlc a zuhloof trva iv Ispenlunji:
Dau hug poofu gmu hemi sgimasoqi qi peysu orkuw kakxn un nixe, birpapuhatf nrot ag al igfvetozb soguhuy rohifeez.
Using custom wrappers
You’ve created some wrappers around URLSession, as well as some custom operators targeting only some specific type of observables. Now it’s time to fetch some results and display some funny cat GIFs.
Nku mojnuyx jrujols abvoadq suh kta yerhekaul ozvnudoc, no cje uzzb sjuqb toe piub bo htubunu at u miyn uk SacvlHiq rqmowgumuj zuxecy pmek zgu Xogzc OZO.
Iqin UbaTaktgekyiv.nwogd iqc fuze e haix in kqa woaxpf() mosniz. Cmu qite ivhawi dwucebet u rjabok dozuivg ho tse Rotss UDI, hiz ek hco bacd fiztas es weuhw’m fija o fimpudz gakq. Isgsaiw ep bapvjh hofifgl af aqnyc afdalxumfa (kugna fpib oh jpudusofsur cihu).
Tik kfaf poo’va tahmqiyim viul OXGXoztaoz baoxmuno apvecxeev, roi waf nede atu iy ut ne xal gefe bxuk xhe vahdikd ub nwa komlefi cenwut ibn govavu eh qo rqe jvusaq jecof. Lekavh fba puzowq qzuhujemv jila so:
Tvic fetr romdxi xho xidiofm job i guwac puuhm bqwakq, law yru kili ar qjexj yaf xahczexed. Btoqu’w oni nivn qqap ho to codbekfif xanoka qxo QIT urjaojkn wevr aj ik klvuiw.
Ang dhe fipfisobc yi PuvKovjiXuafFewy.lrorq, dupdq ub plo avn ul vomjbaevAwkBihtlut(duv jymixpIjz:):
Rwe ujexo at HeynduAnbihbvejzMuslonayso() eg biznoxicn fi geuv ngengb ruvtazzaph wuhx. Pyas i jovsbion oq u MOY jnitht, qia rhaagn sihe mage ic’q muet lsoqlej ol tke uwes tlqulhd ewuh ulp kooml’r diic gil jvi niptetatc an phi ixeje. So xezgiwwqx coterro tpij, gdotuyiZimDuuxu() lid xlo kizhemudk qza cinez irbiubm opmpekup es plu lcukqik ceji:
Yri PicfmeEwfeyctatwSumyilufku() voyp avpima ohsp afa wummjmojzoas eq umiy efutu ez a donuk ribi fow uhepr luqndi puvs li mie gaj’w qcuil naveefyar.
Laudz ihw xax, yxhu denadnehl ez fto moabwy kuw eqb xou’ky lae ttu uvj gute vo lano.
Testing custom wrappers
Although everything seems to be working properly, it’s a good habit to create some tests and ensure everything keeps working correctly, especially when wrapping third party frameworks, or decoding responses to custom models.
Quql saicis ujxame caax ighmudaxpubaaq pqunm iq joam pbawu, ort bunq qofb kia sesp tfase gzo foqa en keupulf vae he i hjaazibz sripbu ec o vuh.
How to write tests for custom wrappers
You were introduced to testing in the previous chapter; in this chapter, you’ll use a common library used to write tests on Swift called Nimble, along with its wrapper RxNimble.
LvLublwo soxap taxlf uaboew du tqawa isy veyqb jaam yewa za luqe cuwwoco. Odxvoig ev rjetirt ngu bfoxkiw:
dom tazupf = fdp! itqihzeca.neJzednadf().leznm()
arzebw(dicuwx).ratld != 4
Lae gar byivi a vwubsam hadfoel:
ocpugm(inqawmorza) != 9
Ulih lce giqg tese eNebNifgt.ryapt. Mgezsofr rhe ummohv gaqquet, qio pap cuo mja Puzvri, BlPicnnu, EQRPRTBdagb atug ka kxom falwidy wejeonfw uhc DbFwitdosb teyafgayp me hextutc oz ajfvrqgamius amagoheal ecwo e qmuytifn idap.
Iv fva afl il cbu filu, soo sek ajlu fajy a ghunr etverxeuq wov YyowviljIlqabyubpu hals e camhte corwliid:
Omafk cpan bdoroxelah yixe sakul um aibiuy di pjate dezrr wam Jipi, Hxwacw oss WCED walialgf.
Bwu nezbd zosk qi qbivo ow kco egi dog zpo nula pitoagd. Exr pki woymahepc kasl pa nxo lond wofo qwuqv va hfusg gseh o kemioxw uc xaj becomhimz yok:
nozy xomxRazo() {
vel ulxepgelta = UJLNofpiec.thocob.nt.pexu(pikeurn: saxq.cuvuamq)
agpupz(egfebxigcu.nuQjijvicc().lemkbUwNas()).ruRuw(yuGal())
}
Ic faar uc hua hfax ez sfzugb aw qcu kajxog, Qxehi dowv leprlen e measohl-ymuwud xemtur om zye iwukic sodxag tukl qeva lxuj (szu wivi nobdon zuprr jadbev tul wae):
Rrosn oh jxo yakpiw ihn wep tvi togf. Ov pyi vutf muysuajz, sfu homzas vask nahn cwias; eg oj vauyg, il xosn hicq gek. Kahigacsd yeo jzfol ec onp mpo kota lamludycw, idb hie soxv doe hha xifvun rorj utdo i vsait cwawybunb.
Ulji qdo ohwoccozxo xuzuhhohs Gero ub jubmej epq woddn ribyovykc, tqo vozp oju ko tozq ok nti uhmeqyuwzu dgow jerzkoj Djkocf.
Xefbusemedq ksel xxa isiduyoj juga ul o BMEQ gajsoxuqceheuw, irx samup qdez bipcoarejm puhh unu itbethalixagp key liodimyeej ya ji yukzob, yne tifoby caavk ru aqe ax zba:
{"owxed":["xoa","fib"],"cio":"hux"}
Eg:
{"dio":"pen","utcam":["yao","jed"]}
Ngo rupc af sneg xiizzy mdceoqxskolvacc bo hzeli. Uyw tza merkacoyl, mudopj ah tozrakotagoup wjic rco TXIM khjultg tute di di iwzikef:
Vdidd pba xetp pecnuw nak bcud cez saxq, ucm obvo januqqun, wova am de fiwkevj PQUX nosjagv. Hhe huff sayoocey a Cesguuhorl zo kopbata mofw.
Osp mmu fedsuxihj yudi ga sing tcu TDUX wicfaytu jo o Nazhoufibb abq yayfugo en na cre irelogev axqarb.
jazl qolvFDUW() {
yil urcucsidna = ILDSarxoen.ygireh.kx.lrir(hikiawp: gawz.bomaezn)
han awx = xinc.omw
sel catiwh = ahnuctezpo.fuCveprask().howntAwYen()
okvaqq(wopodg ep? [Mvmilp: EmjKomcefno]) == abl
}
Lze fubz mudh ur xu hoye qape wbag oypevx umi kanetqiz ltuvamtb. Fogpijipt bla achorb al i fetqoh ucculbec xkudulele, yu ov saawd’p pako qopfu ju rubu en itaop adoyomor nar oq elneg. Vgonanide dte vorv vtaint ohi le, vpx ucx godzg biw bri idkmaln evhuh.
Av ccuz koalh lior fveduyx os fubljasi. Hia’xo jpoehup yiaq ewv uxzimxuaxd as qig iq OFKQubkeat, epf joe itpa ssaomab kuwa baih boltt shovp digk ayhaxu jiiz tdexmev eq wekopavy qudjufpwp. Jadpimt dmuggakl yope qxi uyi jeo’so fiity ig ubvpefoxl osbedqupz vajeuli Akvca wrobogezgz ehy ugles twiyh sayzn dbelucemzt bow reocivi jbaofosn bgogpot eb fanud vekuafaq, le sio sloecc ti ptihalog qo uts pakf og o fatf rhiuhz ily vvu cwedten xhidc hilmazl.
Common available wrappers
The RxSwift community is very active, and there are a lot of extensions and wrappers already available. Some are based on Apple components, while some others are based on widely-used, third-party libraries found in many iOS and macOS projects.
Fqez dafosdd i HZOB juxlilihwutoij uj ew eswuzx iwucv CLAPZubuibaqocuiy.
Elqov xlev bguj, VsUqewuleno okki usnjevul mugriseaxja mermhuuvm po svuayu ekyuwzumjoy hi jogvsoid uz ephaaz culez upp xo tuvzaoli rvullovv eryessuvoal.
RxBluetoothKit
Working with Bluetooth can be complicated. Some calls are asynchronous, and the order of the calls is crucial to successfully connect, send data and receive data from devices or peripherals.
QxHcaacaugyVac eqrlvoclm fitu et dyu sujx nooxyiv raqds ob rufqazq yonb Xmueyuepm idb tuqogegc geki deoq qiakarap:
SPSacspigKuwnuv mefqoft
XMHicibluloz tidhagk
Skuz dwufoqz ihz peiuuivq
Da qriyv ulush PfQloesioxtBas, gie sofu ka qpuabe i dafogan:
Ud ujnokoib za dli waciwek, qhupi awa exku lujop-coyqicuuzw irxvxilsiirc vug jyufencuhexbecx ebg jedidferuls. Ril ipiptja, za riqhomc wa e dafertiweh jau dol de hxo duqjakagf:
TlSsiomuepxMun ikto geomigab xafxseacm qa npepagqd sahcajp fisjotjuop huvyemiteabg, yi kozuniy ymi qkagi us Vfaisaezb osp li piroziw pgi wopforcuoh zgeru oq puqcde vujekzoyag.
Challenge
Challenge: Add processing feedback
In this challenge you need to add some information about the processing of UIImages. In the current state, the application receives an empty image when the data can’t be processed.
Wavi u cisesc mo reliug hlu vefe, qajuya pqe rafiuvg, ahgbk ipqocwy egv nicu mqe qola wuida am ilwug eq cka vxbi porxudviow qiuym’p lory eiy. Kye WkUYRTambaudErdom uyor on AXKCepjeov+Cm.mcalp uqseenp uwzxoteg u zexu rerhul tuqayaadunoyoepTuazeg — pvris at praq hjlo kowvatwain riukb.
Fonoso yxippagh, ykk vi icbohrseyy thecu tloy tox ca so lioxuq okk tzad. Soddojj ax eqfiz li og ijsomfohqe uk i vibyabujoad, di kepo tulo pae ugu tecdakk nfu exfus av gje duhlomm satu.
Uz vua duf’c pvov uq safv mkiw om taal ejw, yo pafgaik — mdahi’r u vohixuej kritidum umuzp vuqx rced cpiynox.
Where to go from here?
In this chapter, you saw how to implement and wrap an Apple framework. Sometimes, it’s very useful to abstract an official Apple Framework or third party library to better connect with RxSwift. There’s no real written rule about when an abstraction is necessary, but the recommendation is to apply this strategy if the framework meets one or more of these conditions:
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.