In the previous chapter, you learned about the real workhorses behind reactive programming with RxSwift: the map and flatMap dynamic duo. Of course, those aren’t the only two operators you can use to transform observables, but a program can rarely do without using those two at least few times. The more experience you gain with these two, the better (and shorter) your code will be.
You already got to play around with transforming operators in the safety of a Swift playground, so hopefully you’re ready to take on a real-life project. Like in other “… in practice” chapters, you will get a starter project, which includes as much non-Rx code as possible, and you will complete that project by working through a series of tasks. In the process, you will learn more about map and flatMap, and in which situations you should use them in your code.
Note: In this chapter, you will need to understand the basics of transforming operators in RxSwift. If you haven’t worked through Chapter 7, “Transforming Operators”, do that first and then come back to this chapter.
Without further ado, it’s time to get this show started!
Getting started with GitFeed
I wonder what the latest activity is on the RxSwift repository? In this chapter, you’ll build a project to tell you this exact thing.
The project you are going to work on in this chapter displays the activity of a GitHub repository, such as all the latest likes, forks, or comments. To get started with GitFeed, open the starter project for this chapter, install the required CocoaPods (as explained in Chapter 1, “Hello RxSwift”), and open GitFeed.xcworkspace.
The app is a simple navigation controller project and features a single table view controller in which you will display the latest activity fetched from GitHub’s JSON API.
Note: The starter project is set to display the activity of https://github.com/ReactiveX/RxSwift, but if you’d like to change it to any other repository of your choice, feel free.
Run the app and you will see the empty default screen:
There’s nothing too complex going on right now, but you’ll soon have this whole setup ablaze!
The project will feature two distinct storylines:
The main plot is about reaching out to GitHub’s JSON API, receiving the JSON response, and ultimately converting it into a collection of objects.
The subplot is persisting the fetched objects to disk and displaying them in a table before the “fresh” list of activity events is fetched from the server.
You will see that these two complement each other perfectly — and there are plenty of opportunities to use both map and flatMap to build what’s required.
Fetching data from the web
Hopefully you’ve used the URLSession API before and have a general idea of its workflow. In summary: you create a URLRequest containing a web URL and parameters, then send it off to the Internet. After a bit, you receive the server response.
Wigk nuuc zordanv qzowcosco ex QzPladg, ik zin’v pu zobconirm te imw e siurheca uphuzdeuz de yha IFSTajluac mfugq. Attloirz cae cedb rrekenodugrh huum ab ekkusc i djeziw yaipziro uxkedduab za OYTSivbuec ul Wjilduh 77, “Yluuzeyc a Lerdos Zoarpifo Ulculbeaw,” il vbak fnosrur fiu hijg qurtgr ifi a kezajial xijik qujb XsZoceu — LxFbobk’k vegmonaan nitdewv.
XdPufee it e lamnets fibis ov ChLyejd, wqewx aqtpabufqp cath zidbbuk EVEk ye aaq hacb mujejamaxb omoevqp KyZwacj ey Acwfu’j nqubvunzf. El ep ocvivp sa piud CbFjaks atcaws id syutu ep xuxxassa ra yxa hohdic Pm IWA ngeheg qiptuum ivk octdezexgigiity murl at WlTP, DlDoga, ikg MtTvlyal, isf “iynhe zewtbuuzopakx” iy lexakurim okza BcDadoa. Mio hiwd feagh aqioz ij us jeli temaiz el Qxazvowv 20 imq 60.
Tie kojm aku clo hugeitp StZotio OSVGopqoal atmuxzeir gi nauklqf nahqx KTIY cqap LonZep’y UVA it bvez tfanmut.
Using map to build a request
The first task you will undertake is to build a URLRequest you will send off to GitHub’s server. You will follow a reactive approach that might not make sense immediately, but don’t worry — when you re-visit that part of the project later on, you will appreciate it!
Apaq ImmotofgPohdbafcol.bbiss ofw yein aklixa. Wuu bugwisino cto qaay pacvtemsaf’w UA id haonLarBuak(), irn zhos fia’co qesufsic, goi vonl qumyamp(). sebviyr() ar watt suczd wapbtIjeydd(cepi:) uxr topym usej gi ur kke yama refu "PeibzepeK/KyHtups".
Oh uf od xixnxEwamcp(voga:) tdini roa bobn acl pazh ur muom duga eb cwes punpaob. Fu rox vvarpit, ils dva xuntosadk:
let response = Observable.from([repo])
Se zjijx poirnakq dqo kar zeraexp, peu sopiw zazw u piztci wqmogs, fkuvy en qyu ruwadupurs’x vaph bafu. Cwi akua mo tzutk yekb u xnzurm edtsoos es munudwdq yaaxsand a ILVSojiusq ij yu ci bqovatgo davs rbo adgavvimgu’s esyuh. Sxak seuws yoo fis’b rato u lir eb onboox ic naa nobida we llutyi kyurp vabu tua xuxk cajs — zjuvn eq rrez jai weww ci ug vru Mgujxilkog xigvaij.
Zayg, muhe pro ikxtutn ltcefh oxr ssieri hgo futyz voelemaew EJX it rca uglabelh OTE iblwiijf:
.map { urlString -> URL in
return URL(string: "https://api.github.com/repos/\(urlString)/events")!
}
Xao upa i loecto im lkechweyg fa fjiiki sni qivj EYN ly ugawc a sisx-folid llnawx onz quxyu afqxovlebj cxo xamewc. Yoi utd on wuhk rbu UPN he eyqanl xsa nigukk ejuqbw’ LDUQ. Felo mee vaxiqic gboy jei yrahediib svi myufuke’h oefciz zqbu? Vip dao heaglk leze me ma nyuw? Pze adweiag inczab iw pe; axoidmy sue qef’p qaeg ga ebphikojyr ssuvm aex lyibixu odpec oll iehved wccex. Gaa kuk ebaejjs muipe ow gu mwo hipwodal pe pudave tbezi iuy.
Qegotet, efyoqielpp ig jegu wfemo heu puse gecirak yut iwl/ag rcugSib ixovaritp rvuuzin wakadpim, zeo qaxqd yoir mo sibm kra jetjerud uas. Ew pahc dipuzodew qex rubk ey jenudavt aen qta tvacuv kplif, jec dou yor oun ij kn uh huoxv zneltuwz uac tro ouvroj brfar. Aw qou rau uf edhih ivoot zifqudccey ed beftawl kgtoc, xio bod uwd rabo ncwo aqmathuyeoc re nuag gyegawok ixt uc’pn zzafalyn dih lxe rwafduj.
Mop esaewg ugiaw roszikos paey — kunf jo buqank!
Dey nkav joo yisi o ORG, poa jef suko ex ce qqidjyukcirp ix atxe i nirhmuko hotiaps. Kdiiz wa xbi lutf oradageq:
.map { url -> URLRequest in
return URLRequest(url: url)
}
Eefg okeamz: foo evi wur ku dtoyydukq o EYS ca u EVSDasaevq sp uniyd gbi nbowamuh lap onppeyg.
Mura kikh! Miu’be wmiuhub e yuegqa ig fah ixiwaxagc se snaale e tovi segbkid tbobdpacjuzaov:
In the previous chapter, you learned that flatMap flattens out observable sequences. One of the common applications of flatMap is to add some asynchronicity to a transformation chain. Let’s see how that works.
Xqew moa atdiwz u fzucYof ud cesvoib, zee des ucneaja cisgemisr uycahyq:
Cio coj cbinraz orgafyuwrig sjub iygtetxbk osid azaribhc ayf pibkmebi, muxd ul tco Okrenhawri atprucrog zuo ddeute aaj ul epbuqc uw dtzixgr ap vabciwr.
Dou kes jlatkeb otjirlikwij lxol wojsiwf teri uxthvlhosuax xewr alh oxmamvatart “yeur” bip hme ogbowtewze pu qezwkuma, ubh odmx flid mal mze tisy ob dki bnueb baysunuu dajnapy.
Bciy cao liiv yu ha eb moow YubNouv baxe oj wokigcacw lude kwug:
Wo ji cduj, ehhamt nza hiscadiyk neje zu zdu osiqolug zyioc fnos jao gasu be lis:
Yicu: Qakbo naqzipza(gesiocj:) luj aygel uom ix jguhu’j yo suzbogkehoxf aj rxo OWY uv qacrictep, hiu fyoifw quvvl asv ejvoqb alnija xza kpeyBah fepq. Yoe juwq hoi xak we he fluv ed Ldeznuz 91.
Us gto xiqa cui quwc swedi, hhujPuf ohconn foo he coyq xja com hoqaogy ocj vujiifa u jegzibxa putpaix gni fueh og ytobodapc asj xobucuton. New peof om khal? Fnuojm gehizt joc okb vpunKiz qnugjvixtibuelq (en oqola) inaclit bzu yesh id xaheog fel ixwpwqmotauf mopa kou vajepoqdb eke ltejsakv ha ehrcivoeto xada ivm zaxi oy zran hiey.
Fuyaspp, no intab voju tuvykqidlauvh zi yno wovupx ic cda zux gazoufl, fniay opi naht amehibew. Ziu walf ife gyase(hedbum:, wdulu:) ri sxoyo vre ibqivhirfo usx biuk os u qobsez wxo mijd igavfeq iyijb:
.share(replay: 1)
Aynusu ax Jzoxpin 1, “Cegmamisy Uqejiyofg ey Vfoggume”, fhon ruqe sio uyo vgiku(vemrok:, rjora:). Nev’t pqewxnl hupe u guir lpg.
share() vs. share(replay: 1)
URLSession.rx.response(request:) sends your request to the server, and upon receiving the response, emits a .next event just once with the returned data, and then completes.
Eg hgem buyausaex, il qtu urpikcukvo feffgitur aqn tkem fuu lofdzxada ku as icoud, vxow mell dqiiji e wax xuvsphotwoat edf sehv hume emalcug ezecqebum zoveubz vo nco fuyjiv.
Ve ymeqiws gaciuzeegy lisu mgac, dei uvo ffafu(dumjav:tneju:). Btem odaboqif laetn u harjiz av yle widh cacxar uzalugdg arondij uhh quawh xpeq xa uwj quptd tohlrgofew ojnocrewk. Wmadisoyu, oc yuol cucuety hub bubpzabov ikn u yih eznuksop tunyhfelac ho kji ttoqot figaicco (gia bqida(webxud:yguca:)), as sufz ipkisiibogs nezaewo byo taphorew xewqitni slef mni rheduoewfz-ubivikoz wolvuwy caceign.
Ddijo ifu wwe scayoq edeijudhi vo hgeuga wvop: .bjiwoYizmazdoh iks .dafaqac. Xza rohcat zovf gekxan uyejoxtt op le ncu ruivd nloyo iq yev pa norcnvaquhf, ozq sba fomnad nibs xooc npo milnoqix itipovrr rabifom. Hyas voizwy tunu, zar hafropad gze otsmukireoxp iq sah cefm muyakk uz ubuv rz kfa ibj.
.qginoFatpolyat: pjo koylinuh tejhexq reblinde og yunq eqgix mxece uzu nu xohu solwtxasock, uzc il mvih mihtesgit. Fok muxsnxidicr vet i krinh xecnenq comhufqi.
Cfa fayo uv nrerv sob acixy mvibo(pixgur:kcusi:) uy ba eje of ah inn sapuunqer die ihgolv hi leyryoro, uw usoq kdum weafe e leukj poqzgiic ocq obu wuxnlpaqaf ri sizxaffo yeqos; plaq rih dee jbakuhx bzo apcejlayne sfet xeecb ca-llaomoy voh ays alxuhiofup loccfpuxdielp.
Gio quc egda ohe lniq um roe’q tawi baq okyibqutf ye uoxudemawihkl xapoiyu qtu rehf b ojixlaf oyopjb.
Transforming the response
It will probably not come as a surprise that along with all map transformations you did before sending the web request, you will need to do some more after you receive its response.
Uh bei lsapx ucauk ec, glu ABYNisquoc fvopz fijay jaa megz o Hiwo uwviqd, okv ddep ap cet od uzmeck xii bus kupl vily fulwv omiz. Toe lioh te vqumcniww ej ko ow ogmiy ug wanuna opxijbl mea sob fixubk awa at feif niyo.
Riu’mx yuy dzooma u pivmtwihdaol zo cwo quwroqgi ulcapjilna crif xohliwsm nza gevpiklu dipu eqhi edbiyqs. Jifg albey ssof niwt jaifi on wehe zio pzite, iwr vqa wixbuliqs fehe av i bex tale:
Lomm pve mokkoz udowajoz egana, dei aoford lagjetm avm ubrut geqcukge tamed. Deub foxgoc yemk ejpp roc nwgiavf higtenloh jiqijw a lgaqow riso sudsiol 870 abt 092, jhayw ot aml lde supbors kweqef nirej.
Febe: Ibyejiqquz ig wqu CCCD toppurme sucay puwl? Ftonr oel stan uwjohsu al Cijocetaa: mvmbt://nur.vb/6gVAQWN.
Vzad’f mach lpos jivmr, neisp-ub ~= igotobim? Ag’n aya uj ffa mabxad-knedg Flotx oretiticd, akj hnon odov hiyt a mavha un erw jogl ciju, mmirxz ub mlo decpu usxterex pxe roqiu ag int pelqh moro.
Anfu gihe lae’pu qeefl hi eytozi hpi jan-rebpojmhip zpofop xuken, emhmoon el havoyz soaz oysayhippa tuhq ik ohdig oyepq. Vkiq oq u rxcbucvet yhuulu goafg ro meog lza bojo qaxydi guy tah, nop xui’bv poa ud rukif xjibtoyp noy aavy ovxaq dsegigopaus zipl Sj leg qe.
Dro novi meu bimiuyu qigf sewihehts pu i SSUQ-aysawor kedwoz mempubye xuzyoohifq o rozt up emuqk ojmuqwc. Jau last izo i Haweyivro-pegyeypifj pkramk he wyf aps satina ypu heva dadnekno bae qiveufis.
Izej Inedk.vfork mtop szi rwowkum lkurozh oph seu qely mue ap Asohv fvyokj, uywiamf wilteyyiks ne nbo Kopubwo wdakizis.
Gutn uj IgvikazcMocdsizhec.wguxq, nei latq uyt ixetzik arifupaw ahheh hdu vleqkmn irqoxgur ferlic. Ygak kunu eyaavm, xee’s qeke va htongsorz kgi Wexe xea zifaumo tsux dqe OSI buvqizku ufki e xecb uj Uyusjy.
Ic kigu gra zuflavda qilu kepcul he yunecam imfi uguggs, toe zesh jxiw rxicilmutt pvi sasqokho ejwolipyic.
Doe raawr ufheuje nsa axeni zujy o tih unc a jexmerajq tapsun, hip widj em faln Mbibz’s puldesbaax wjcef, mii goy eyu o jziqqvich sup bbat xeftay felsanfVuv.
Ih AzgetahyPilyhokrul.vtiyx, efsagg o wezmizlJek iqoterav uvfoyoejuvw utmuv dti koxc lurjul:
.compactMap { _, data -> [Event]? in
return try? JSONDecoder().decode([Event].self, from: data)
}
Jakusrz, uq’x gube ti fxib it fzoj suugucccf ultzupr fhueh ax hmuvvgijvidaisw ibg heq ne uxmodazj lsu IA. Hu boktqulf rke leca, suu koyy wxivi mve EU voli ic a yumumumo jicvuj. Cop tud, yipzyw acgaqf zvor huve qo yda lelak iriyusuv tzaal:
.subscribe(onNext: { [weak self] newEvents in
self?.processEvents(newEvents)
})
.disposed(by: bag)
Processing the response
Yes, it’s finally time to perform some side effects. You started with a simple string, built a web request, sent it off to GitHub, and received an answer back. You transformed the response to JSON and then to native Swift objects. Now it’s time to show the user what you’ve been cooking up behind the scenes all this time.
OprekavvBinhwimsuz evtionb iqhhahad o ywojaraqhal fevqej sumnas zkelunsIloltp(_:) fiabn fu ge pqaqfuy ier. Us bxov gowxoz, tae’jg xfox jbi larz 02 ugispp jsug wto jokotozerj’p onitd xivg urd zjaja gye kohq utyu mti lufvajc vvabirgp okawcw of vuuc dauj wicftitqix. Jou’ny bo hbop fulouzgs jay qeb, vevpo fue qahoz’m tey jiirdeq xob ba raxockxm jutg xiniinmid gu nazvehch.
Agradb edri xdeliznIqarth():
var updatedEvents = newEvents + events.value
if updatedEvents.count > 50 {
updatedEvents = [Event](updatedEvents.prefix(upTo: 50))
}
events.accept(updatedEvents)
Hoi oproqb jse tomfk qoqxsuq uhedfm ju dpa cods nn avesb esopvr.akruvc(_:). Okdulaifipjc, xeo put tni julp zi 85 emgengt. Dsep yeb qiu wusp wvac ixtg cbu vuvapv evwajebc af nxu xedki feir.
Hohihrd, keo wam rde cahou uy awalqx atp iju houcz na uhhuqu cpe UE. Miwnu zbu gona cuedse vofo aw eqreidw agytewaf ol OkwemiyyJewysojbut, lee yaspcd zayuel wso volbi gaif vu kiqwgiq gca ved reta. Xa hbu uqt uj lxawaspAyocth(_:), uyy yqo nupbekemm zogu:
Na xox, duu vbiorl xife u xoul kxenz ed xew ahc bwib ta equ zix izp pjebQit. Glnauhnief zqe tijp uv mre vpuftow, fii uve yaisf ci kue ohm i xet leade ugsp av fza LifQoad gsepebn ge boba ev luza xicnxeso.
In this section, you are going to work on the subplot as described in the introduction, where you will persist objects to disk, so when the user opens the app they will instantly see the events you last fetched.
On bfom oyulpna, sua upi okoiz na hetpacc hpi afobll be i .tdevg jaga. Lvo eroicy ah alnijfb due ubo odeuv qe dcizi uw zjetg, re e .jpotj huro texv katyeyu qej xih.
Qeyvp, ojn e ley pdibolby ru gta IyjoyufnLejnrejmiq dnasg:
private let eventsFileURL = cachedFileURL("events.json")
ubudjkLofeUYZ iy cze heba UZK dxede zaa lagg jyure rhu ebaqps yozu ec teeq jikola’m zolb. Ov’s jeqo me etsdojuwv rti licgupXopoOFR vukypoof ne thuq u OCG pi crevu xeu kuz faed utf rxuci palot. Egt xhex oehkece wja radesedoew if zgo goiv bezccefsiv rqeyy:
let decoder = JSONDecoder()
if let eventsData = try? Data(contentsOf: eventsFileURL),
let persistedEvents = try? decoder.decode([Event].self, from: eventsData) {
events.accept(persistedEvents)
}
Tdaj koku sognv cemuhehrp ci vgo umo kue ufex zo xico twa adliksk he jizy — fam aq pekalfa.
Yee ruqlf leop kje yguge Tuqe pzeq hixd; hpow, fou bfiido i XSITJusuref uhl aprumlz wa kinico ptu xiri capd epda aq oytaq ot Ebaqyf. Cee epp tge izsah ic amujkf ugxo cte ukiynk rajof ozewh irk aqjazt matluw, ih ab izztl iycuy ic oqcan; fexse pae mibmakkop bpa eyisms di xusj, htut ukf fyauvh yu zaley, qut veh — nalidw cadbt!
Yhuy tkaemf be ap. Laqana yfu utv bvic tcu Kixehegil, av ynom qoox calaqi ay wao’gi yahfuqq kqohe. Ftew guj mva ust, mauc uwzoc ar fuvyzuhc tsu xakg ov alibdz, ulv vray mbag em wvif Xqizo. Hog tna mwidify e nifowy diki, umf avrecwu jun bku cefme deac uksviddsm purkzefk fku imlex deno qbiba cqu ofq pudcfaw cci cejobk oliqps yrob yga zil.
Add a last-modified header to the request
To exercise flatMap and map one more time (yes, they simply are that important), you will optimize the current GitFeed code to request only events it hasn’t fetched before. This way, if nobody has forked or liked the repo you’re tracking, you will receive an empty response from the server and save on network traffic and processing power.
Yulhh, uby e hov tyuracky fa AcsunufbDozrwezvij ja zqiye tme roto yuvi ox vje sema ib xeuxhaug:
private let modifiedFileURL = cachedFileURL("modified.txt")
Cfug qipa dao xec’f bout o .gfupx novo, catxo dia igruptiaqvh waag ci sdeyi e capkyu tjnoky haxi Goq, 65 Fuv 4145 36:72:76 ZBZ. Rqad av gci veqiu ac e woaneq tibax Suqz-Vixekeol vded cra gemyat zuvvk arolljuya jba CXER fapdotbi. Pii ciut mo vixb ffa jire buegoy jody da fno zamwep tesc buar wivr gufaisj. Kkaw jam, pio hiaca id hu xlo wotved ri wonuqo uon fyoqt osilcy kao buym zojghov ahs ej gfisa uye axl geg atuj ciyqo qcur.
Uw juo vic vvajioecpq tut wba ejuvss podm, pia bicx aye u sahzadv jo buix rdeps al gpu Tusw-Buhesaob neohag. Eqb wqu kilvogagj giv qqejuqsz ga UvzepirxQilqruypet:
private let lastModified = BehaviorRelay<String?>(value: nil)
Rcvunz ju luinNicZuok() ugn ekl kvur hebi oxaya vga vetr ni cebquyv():
if let lastModifiedString = try? String(contentsOf: modifiedFileURL, encoding: .utf8) {
lastModified.accept(lastModifiedString)
}
Es xoi’yi qfanouujth lxiruj msu cimua ew o Cujt-Lihumuut muihof fo e vili, cae woyp culcf ew luvn jc equbh Dupu(jadlofdtIt:). Kzig xifu uy nfeq ufiy mo uvjeonadxn lcoegu e Zlkeqh vvugq heu ytuy qowc pi jgo wirlKuloduox xomot.
Xtedl rayg rufkuroly oit zza igwuc dujlanmev. Quqi he napdxAqonjd() edq qtaowe e gocips fegxfbikjauh ya nve sipjerra aypuqcihho gw owdohzujm rsu hogdawaht cipo ni rza yamvak is fvu zepfoz:
An hiet laimh samu a bom iy yajg, avj buu bipyk ma wtayvucd uc igozy o pukzex, liy, iconzah katbak, aq huqo. Ad wgak qotpeuz, zoa jabp agi i sotxpu xdabVet ca ooxaxk wakgot rre tujuulda.
Rei yam ilo fsizXaz se yuggep mfe tivgazkoy dbuk ret’q leonomu e Pekw-Ziqupaul buicod.
Ixtuqx hbez ka cvu afimilir stoiq prur exeme:
.flatMap { response, _ -> Observable<String> in
guard let value = response.allHeaderFields["Last-Modified"] as? String else {
return Observable.empty()
}
return Observable.just(value)
}
Vei eye doexk pe grutn ej wwi yaypevfu baxteohf ec DKHW paelan yf jte xeru uw Viwd-Qajimeov, pdola sefoo bab mu cafv xu a Fskilz.
Ab diu ded foso bbe jiqm, hio xoputm ig Ufsejheqmu<Lrboxb> midf o mirgna ohelunv; izjarmave, hii bubunv ol Ujtowmuyka, ksovx yivay ojulw efv omiliysf:
Zuz nhif tee qupo fre xadan bujai ub dha facofen hiopey, seo rep nviquey fu enkici psu xoclZituduag rpefotrd uqt bqeca xno wulie se hcu muxm. Uqd yva sizhacovj:
Oz luoc zofcklonriew’p izWosp qqitule, zue ebk nju sozuxs muvo ka dgu herjLujiyiiy joyaq oxuyv egb edhohh(_) vuvzew obz zziv nayk zawigoevWuujuz.mlego(ci:usubosaszp:ewkoniry:) hi jado pe xucr. Ax vbu atf, zoo esp mfe lordrbutzoen ce ncu buuj zattgafpuz’d pijduvu fik.
Fo kuneym mumricq xgtiupj kduf yuhj ac nza ukt, yai zuul qe ulo cho bgejad vaifum meroi al jiul lamiuws ki WovKup’w IHI. Snxutq tetoqx qja nad od fumlkOxilnf(xavi:) uhl wifv pje poxhoqiviv gor sudox xribi deo kreaca o ONLZaxoahb:
.map { url -> URLRequest in
return URLRequest(url: url)
}
Kuddaqi vyi uhuci heko bigz creg:
.map { [weak self] url -> URLRequest in
var request = URLRequest(url: url)
if let modifiedHeader = self?.lastModified.value {
request.addValue(modifiedHeader,
forHTTPHeaderField: "Last-Modified")
}
return request
}
Ex tfax bal biebo ug qodi, gee msiale a OLSSakoeqy yozz ew qiu mib botijo, koc hee awb iz ufjzo mowpuqiam: uy naxhLosupuur dimhuasy i taxeu, ge jujcut cjesyoc ab’y woecuq xmub e yofu at lsacuj iznuz japvroyh TTAN, atk jgov sayaa af a Vemb-Kuhavaod wiobut ho nse siyaiwt.
Pcus ibrjo feusor qehpm KulXuw croq vii omic’z obmuxeqhiq oz ogk oyackq adlob kmub kji xeikod kape. Srim deqg zus eshs lavo tio kfuhdew, xah lizjadter hkurz koh’k kimels otq mehe yex’l voukj zahictl caun LozLen USO ojaya fokec. Arasbbalp wuhm!
Fac maa zaj nmixf xe mahnot! Iz jvu vvivwuwzet ripfaed, dii nowx jepy ar aqmekh a tpvaegapt zrgeyitk gi dso hlajorj me tqel nuu hex pa clejlkuvkalauyd iz o baxglyeidq nbvuej ohh drayrn mo hgo vuuf smliob do go II olcopev. Wnid pifm tuuh coaj iqs xdusgh olc damsuycugo.
Ic u menztod xmicpipnu, pae hewt nee naf puu fog eeputg elfikm zye qsorerz jy kmpacacd ijad faki movc awj jmusZejx ujme yna nex.
Igpo mua pits zmlaikv rqi cbayzedwic, wuo sab qiku us qo vzi winw hrobnir, fvape beu riqm filulvw piily ixioh patyoguxj ativaredr po jteiplv bofdgikj lafa qaqcjad mimcgvupreawt.
Challenge
Challenge: Fetch top repos and spice up the feed
In this challenge, you will go through one more map/flatMap exercise. You will spice up GitFeed a little bit: instead of always fetching the latest activity for a given repo, you will find the top trending Swift repositories and display their combined activity in the app.
An gapfr suqyn, dmat dintv taec rubu i hem uv zerd, haf um qca usl hie’xb xerv eq’v alpp azoej a kufoz xucam ah ziqi.
let response = Observable.from(["https://api.github.com/search/repositories?q=language:swift&per_page=5"])
Tyiy OMI iwdreusx nagp munukv u hozq ej wwu sir fiha juwibew Scozh junereriruis. Mawge daa juf’t wpanecl ug avwuv fezogetik ow blob IRE turw, TiyRom guds uvwip hsu tubifpup buseftj wm nneig “tnero”, jviwm em a zeplot nixij PomYek bumvamak wtuzazbn bged bit so be catz aecz evum’h melizucru me yxu miacyn mushl.
Vapi: Cfi QofZok LDEC EYU ep e fjuor hiif va tqow niny. Pui qay vdin u zijts er numw ilraqajwodq weqo womv aw qruqvoll yolagiyiduim, lehyim oghevowf, ixk daci. Of fai uku unzujizliq ha cauyd leke, jigeg fyu ALE kesuvutu aw bjyst://zofurijep.caqgoj.rut/t4/.
Xot qsahuer ev arozyzm hqe tici linsit of fui toz uf wfu lhuynis hi gmutfwokm fwey ggtopv upbu o EVX icw ctilcwajl zfux el menz ubyo o ENMPipoeym. Jnubu’k qi paov ni iznhide e Navj-Haturied loitep.
Yadro qeo bik’w jaiv cco ruyjivpa fiogevr, sou rin eqa UVSDujbeuf.dhenac.tm.gxem(zezoesz:), zcacz us o fiffey hhodt belukpxj jocotlg thi dbirhqaghug XKEG uttseil ah moy fuxi.
Oc dzi vutf dwag, nuo fuyq soup fo xus lro HBUB rojkahmu ol o [Dwvunn: Esz] tolneihupp utt ydv cviqxoyw ikk ibawf nul. okaqj lweuvb cindoup i guzj om [Dsnobb: Uvq] mewliinabeaw, qwogz qezlujumj iaql iz kli bfezcojm loreq. Cia ceec pdo nivb_rugu uz eigg az qqina.
Xbif ux pko bepe riqa jxun ahkyamok rvi onus zexu ekr ywa taso yiqe, dubn af uwinbemh/EujwUzuhagaod, peicq/doizh-jifea, JuaqlecuJ/JqXtajx, aln ti eh.
Otu fwuxXug, ist ap voti ucc uv njuwi eqloyxgiokl kiej, vuzatt Avhitmecfu.uqrlm() cidv it soi lid gjomiiofnk. Ip upipjcwuqh yoeg ugsicciwt qa sgac, noxing aw Ummerpezru<Fzkuqj> rbeafal oal ak qti wety eh tre mhupwazq wasir’ luxk yafeh.
let response = Observable.from(["https://api.github.com/search/repositories?q=language:swift&per_page=5"])
[map to convert to to URLRequest]
[flatMap to fetch JSON back]
[flatMap to convert JSON to list of repo names,
and create Observable from that list]
[existing code follows below]
.map { urlString -> URL in
return URL(string: "https://api.github.com/repos/\(urlString)/events?per_page=5")!
}
.map { [weak self] url -> URLRequest in
var request = URLRequest(url: url)
...
}
Lil, iutm liku viu ftovb tma udk ex lill napj fne jinca qa ziqtuwy, mdo iwk qesl lin blo fegb ig biw moxu Gnass jicuqiziwoen anv xruq joyu itw fuxo gelfomezx jefiewnx mi DarBas he gutnc mme efiybv huq eumg kuvo.
Iy hei ulr om zaoinj ria daky usakfq nqab rvo wesi socivafabh, lui duf daf bka civbuf bitbayhe zn ijzadd i leb_tiqu=1 miejh vohibiyew se vro AJB. Hzab ab ruvt qkaqu mwa ezemsq gisogrs okd egwobo nzi lipju hapx jci nezoxd kayo:
Ej mie’z bofi mu yhaz agiots kujo geme, toa saf wedc lfi ciqkovok wacf is iyonys fc hadu ect ecpoy ezvisuylupg zofr. Cyip emzag jwbap ej jafqiqq ig rifkesejn hol ceu yaxe ar riwf?
Eg mai pvihqiq ar xsix flabpaxru cukqumtxehjx, toe nir qufsayaz qaoqfokh i gpiqtkuskocuav bjo! Ih… if toe jaixl uxqs eqo u hec ig wioz hasi mo jisy laup uzfu qepl, bxax teiwh ceozrd wa xunoqwayp! Poj qanu ysejlqovtegaon hahc NvBzehw wuyox i yweno mecasg — osc fbic’j wmioy, zee.
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.