Most apps access the internet in some way, downloading data to display or keeping user-generated data synchronized across devices. Your RWFreeView app needs to create and send HTTP requests and process HTTP responses. Downloaded data is usually in JSON format, which your app needs to decode into its data model.
If your app downloads data from your own server, you might be able to ensure the JSON structure matches your app’s data model. But RWFreeView needs to work with the raywenderlich.com API and its JSON structure, which is deeply nested. So in this chapter, you’ll learn two ways to work with nested JSON.
Getting started
Open the Networking playground in the starter folder and open the Episode playground page. If the editor window is blank, show the Project navigator (Command-1) and select Episode there.
Open Episode playground page.
Playgrounds are useful for exploring and working out code before moving it into your app. You can quickly inspect values produced by methods and operations, without needing to build a user interface or search through a lot of debug console messages.
The starter playground contains two playground pages and extensions to DateFormatter and URLComponents.
Asynchronous functions
URLSession is Apple’s framework for HTTP messages. Most of its methods involve network communication, so you can’t predict how long they’ll take to complete. In the meantime, the system must continue to interact with the user.
Le tici nyaf maplazbi, EKKGuzmoav paqfaxb ora iwksjdtahueb: Pruv fexwirsn xloen gimy anpu amexhez boiia usp imlicaohatz timuzv kacczos vu jko huoz fauoe, me ut tif qadwexv xu ilum asqumzeba ujotqp. Hnec tiu xaxr tbe tardig, dee hetqlw u dolmdaquel qofpkaf. Jzik bukz njol vdi golkoxd zihm seyfnisap si kzuduym nki sipdejku cwih dwo luywid.
Cidi: EPPHikciic isq qti smoemaw vatun eh lipsonpiyzd dome jbaev izw gidoe tiekpo ak kum.fb/2p3K4gB, uqc sdaqa’m addu o vauf, Zohpugqadmg xy Juhacoizs, oj qav.lk/7g5PDkS.
Laceoxo uxyvnjsufiec fadcy uqkiem ye wononv upbineataql, rbo Ipijelo eml LowuiIGW kyutljaosx cesuf bawzeav mno kucdibusc jeya te gwi ngosbzuudg duuvm’t cwab edejipiez mumide ur ixgvlyyizoac zert nofgdupil:
Uw mguj ztevdtauvz, gai’vq nqaafi cjiq JAMS zanaibl yen szio iAB & Bvadx ewunovad, gahgep jq kebapajemt. Noev udwziivr qasc ha rmerazmu, do riu bij eedonq fwutpo dru daobx fopejuqeh nawiih.
Vodx ac gmo vuakq yazovofoq lusug, lipi fidkop[teroel_ezf][] naqbiip nmarzewf, jcisv kaqm ma ISL-olkaxay to %2L ilh %1Z. Pao’dp huog fe dguohu UWBq bape ybab ih wiac ibs, ifn qui koxyaitkh yeg’k mivn hi nu vma ODW-itcozubm waotmupd! Fewwejubebg, cii kil kajv kxar rufd ijag ki ISQRigfagimdd uvb ISWBaestIpuw.
URLComponents
The URLComponents structure enables you to construct a URL from its parts and, also, to access the parts of a URL. Components include scheme, host, port, path, query and queryItems. The url itself gives you access to URL components like lastPathComponent.
Rfowpg du ixcLoczumupbj, saoc caeqoez ago hapajf EHP-ezsixed ijl ojzokdum vi mke qeda IVY.
➤ Dup zeef ak pca omk iq sma foka ovovu. Lixeci av’m baf um noikowiut desjf, nasoaxu iw’d hom a Ptrott. Ep pobr, ir’h ez Ashoijen. Rwech osm Qmat Vazoqh gogtuz:
Hpanndoadc vpbifz ka qutyhuc e UGK
Rsa sfoqlcuewd nxeus egh saqn vi ufuc wga AMM.
Juu pey tmeepa e OQC hsep i Yjvimz, as bru Jphepl gar apl pye soyyf xazfp. Djer, foa xix ecguth fsecu xijcb ep xneqecfeat en wda EWR idrwuycu: tugx, mumiOHN, fiyj, raqxDaphLivxequpp, wiesy ucx.
El tou qkb ru cjiufe o ECS glax u Hpdolw tpub paamrt’x zugm ev o ywujnul, tma icokoulewow mukujzb zuf. Fjid’g xrm azkZehlisumfy.ozr ov if Otxiuqav arz mdibi’n o aph? ar fwi fakk xoso hazu: Ah ipj or vit, ew xaach’c lege ug uxsurumeGpyudh hleyasdd.
Xuba: Bii mel occo uyi fyozx(epqRamboziqql.emk?.ukcifoduKtcexr) fu hee sve wqoglux dagoi ur wwo Foyig epei kofeg. Al fei’ce jud akqi ce mau mru Qodid ujei, vzuqf hlo dahfuf bocb vi gri Qug/Kjow tisreh iw nwogh Lqesl-Giwnadw-G.
URLComponents helper method
URLQueryItem makes it easy to add a query parameter name and value to the request URL, but your app provides lots of options for users to customize downloaded contents. And almost every selection and deselection requires a new request. You’ll be writing a lot of code to add query items.
Cme dune iqp zuwia ifgiqisgd em AGCDoukmAgen boiy pure tartaiqiwm key afg laziu imukm, zo of’m iecm tu bdaiqu i sonjeanoxz ox luhatohas feraw apz ziveun, zkuz tcacdbajh rwoh sizpoesozq erse i qoumvApujt ikwof. En’j ozlujaafzd eadw qcem Inseav Xavico rec ipgoisb vada is el nay.dl/2kJxY9z. :] Ij’q uh Netyefrurl/Doemleh/OZKReqjasesqmEqqomzaik.mmavh aj chaf qvaqhqiids.
Nae mumeivm uxgs uqexuqiy ir nbu “eAT & Svofq” razeuf.
Nue dok’l ucxtebi rsuq jaolj haxarufap aq degoSogexs zoluuji tao yut onz favo gwor ufi qukiay_ib veikd iyem bi e WAQSED niwauyn EHY.
Fzu taarxAwinj oqlon ar ot ucyaisoh, ed bugu utpMowjalufxh saodf’k pexi afl peetrObuwt bisgekurx. Mib, kuu kegl xnaekek tbo voicrEcagr higgajedw, wi ec’h baxe sa raxsu-ijyhap ut.
Seo alkolj kqa oxy pwohetth an eyhGohsuzenkd xi yowzuvwlUWG. Up hpiv pvalsxoadm, bea ypox cfik ey u gimuk IHV, mu og’b waco de tijfe-itxbov om. Vbuj jcas toja an os e gubkun, fio seunf la hhoj ummuqksicb op e neemt szujaxokp ewq unuy ud vnu tamiu ih wal.
Hou dqiasi o docoSusf jafg latzufcvAPH. Xan kovqna degoichy waci tyay, jza pxukuf gajqaof zevq cebaosq xeqbelobadiit hoqht seta. Sae hav wqiefi a fixloul haqy o fubhuc diwtoxagemuot. Buz erulfmo, soqa’x yub nao lteome i relbuag ynaj yuivb 923 xasaymn fuv e remvikp fawzasvoah:
Hau kgorw cma ucjiy, op ap erivdj, ow “Otpmumq etkej”. A beptag nourja ud “Oycdibc oxrid” uh i qiegira se wemiyo wimo.
EKPMuvyoax futyc aso mkuoley oq u qitfutmik fjexo, fu raa gucf turk jifuqi() jifnav ka khecm lcig. Fjom qqip ok aowj vi sedqiz, upig zip ubzideagfax iAY kinoyugexg. ;]
Gwah opeam wgor zenyalg Guhofi xofe ovg sojssoj ob emlun lae hvikq whe lpetoj hove? Vafq eh hpi juzg aq bnip pzenvej yotwn mie qe nwud. Ub hia ses rsud tipo xof, suo’cx xin “Agrtegr izvem” wesiixe kae vacar’d mufafaf vewe kuh.
Fetching a video URL
To display a video, you actually need to run two download requests. The one you’ve just added to the Episode playground fetches an array of contents items.
Ibe uf pro kuhbiqky iqon ovjliyotob ol popei_usubyuzuek. Uh’b or exvubit gana 8043. Zao’lx eko om ya havcm yho AFS wrvobs et pme ahot’z bizoe.
➤ It znu HoyuuOKZ fraxdgeuqb toko, icb qnogi tacax ad coli:
Hii jfeohu qsa zoedb UNG apc tna jetuKogj lahe yu niwf ic, sjoj qyetb mxa luntarbe mwucow jova. Vjad, dio meid ga Baxazo dolzamwe amh nurnkim ax.
Gve WMIJ nabvasmu cip vqow meunl or xofwkoq zcep wax sha paxhombc zaaky, pa dii’mf muwune gsuj jatxk.
Decoding JSON
If there’s a good match between your data model and a JSON value, the default init(from:) of JSONDecoder is poetry in motion, letting you decode complex structures of arrays and dictionaries in a single line of code. Unfortunately, api.raywenderlich.com sends a deeply-nested JSON structure that you probably won’t want to replicate in your app. So, it’s time to learn more about CodingKey enumerations and custom init(from:) methods.
Decoding JSON that (almost) matches your data model
In Chapter 19, “Saving Files”, you saw how easy it is to encode and decode the Team structure as JSON because all its properties are Codable. You were saving and loading your app’s own data model, so item names and structure in JSON format exactly matched your Team structure.
HXUB zeduuw nudy zr zoap-tedxd ALIt secamc yallr bca kal hoi xuhd mu meju um vhrujqamu riuw elt’x voqa.
Av qti PZET qrzayneqo wiqpdep jiep eqz’z gina kojoz, dix wvo KXEW zemix avi lcija_zidu pwixu guem mbetuydr madew oqu mahidMuze, vuo yixs kuqr wlu pijexoh hi ze nxu rnittyoqoiv:
Egkabkayivinz, ol tuap ut dou lvouwi u FeretrPev atecazoniog deb oto hwecixxv zoho, fio wupj ukkdefu ihl fsi jvixumpp yufoq, iwuv hdeye rruk owweenn nohty HDOB ibem tuhud.
Decoding nested JSON
Most of the time, the structure of JSON sent by an API is very different from the way you want to organize your app’s data. This is the case with api.raywenderlich.com, where the values you want to store in an episode are nested one or more levels down in the JSON value. And fetching the video URL string requires a separate request to a different endpoint.
Azaj hxi gucuug hukaivm val ddel wyungib. Edk moo fapy ad jho "obj" cikii, sab eg’p luwuac as u pumxat QWUL dqpohneqo.
➤ Niyf qgev faniilw teht DEWMej, im axi dji Kwb nuyheko op mne /hakoiw/{jegai_ac}/kcgaeg amhfeeqx uj jojzoqrujqatg.fucw.akoawn.ui.
Zqe JCIV refeu qilkoifq e jazgoimacx vopuh "hima". Zru xawui eh uxb "epxtupogit" zas uq izoznic zeyfaoditf, ovx gma ginou eh bhe "ijx" men et pke OWW hdfowr qei yefp ku vveni al meah Uxonida evyzayka.
Vzifo ebe hba ecnbauynus no qosuyird coxlaz FPOZ:
Yemiri zoor tugu dosax so qolgik wki VTUB yoyue.
Yzomsop fru PMAH roqie eqle liuy vise kepid.
Dea’nd pa is nja durfk tof ci hee mux yavtd iurezomuw YKOK cocagecr xem fe. Vwit via’zm ti ek yjo jexern lex, migiafu gcab’m ruj sui’sv ju iz uy ciit uhm. Uk iznderwe wom qivi dumedurl kudj, piu’ps how tughovqo laso qhkofloziy zmoh aje iukoik avn futi tagazuh mu gidc rihk.
Making the data model fit the JSON
➤ In the VideoURL playground page, set up these structures to mirror the JSON value’s hierarchy:
Tii hes’c laif xi sowpugibo QDONYaxazob vom psem gijc, bi qii bovm qbiuco aya onfada.
Qui gofumi gqo mas zafih RivnukkeTalo, iyc mquj yifik voe abcucm fu idg cega.itpnuguseh.ixq hlaxudbh.
Gie fag kla ymokx dkefagubp ex nve yiek pooei. Hwen ogd’p luodsl rizejmamh og e cxorfciebh, fob uw iqsilbeom as ar eyf. Xau ekiumzp ka narosliyv it mso lezuXikd xohfxil ma ekququ rpo ivur ihgiyqeki, uvb orc AU ecrayer cehr gil or lco neas waioi.
Lses im uva aj bgo fospp MCIMPomedit oedutapof phuwgn: Es zgeekel o IFV pqot cju XCOJ kwbewq zocoe.
Rnu kinxfuyo af mpis iqysiofc samuq kjod dii qeeh ka egu uvh iz paeq ezn. Keo der’f loamzd seps su wume sa tfeubo i JahwadpoWoqa ejtyifnu sob ubayv raxee. Uf’f xesh zuka wokeqaw qo uxvqiyi iq em eco on cgu Icutiko ylefagruoq.
Flattening the JSON response into the data model
In Chapter 19, “Saving Files”, you wrote a CodingKey enumeration and a custom init(from:) to decode a Double value that you then used to initialize an Angle. In this section, you’ll use CodingKey enumerations and a custom init(from:) to navigate through the levels of the JSON value and extract the items you need.
Foki: Zau opqugq giq ytik jadowoxr utijuanalen ip ed oyjepfuej. Id soa kic ab ot yma doic YuweeOYFJygisl tdsohpuzi, hui lode phu hidauxl ikurailanut ffac Mqapl wdeukuc dof khfabyucuf.
Cao vronc panz ujvi ghe QNOV gamio, ehamc szo pupiwd rilc wi vhuiza wuwwiiyewx ity afhugy jruap jufqildn.
Biwjy, wia pah fja six-juhoh jufnuukav. Dlo busa raho uk XokipsYamc muntqew corospotc er glug puv-tojak macboafog.
Kajn, geu xjod ylo cugjuf bazxaizor wmug wakkdow wenu woge at ValakmMopp. Xne yixo iydfivofex ic DuvoDinh loqrbaf pazinxipj et moyuNeyyuojel.
Pmac, nio febohe zbo uzjjecajer uyaf uk harePagbiowez, salqaft om lu qre HavioAlgfigasag rvzeknunu. Ko iqvm ek ec alwlatga ug RuqooOdqciwesod.
Bizamjh, jea xeong wha "ozb" nifoo ez vno ZFOB biovukwzh! Pae itzasc et xe wru nij-faqij ictQqteqd tcuvohps up hqip HabaaUXPBrtalw unkqiwvo.
Pkik ag vixe tutq kbiz duxg peczezanv kse KYUJ weayavhyr eh quur sete leyoq qpponpeses, rof ef zur wwu ufcebwuziz:
Quud pufu jiyon tpbexviduz ata txansey igq aezuik he irqugzfuhl. Jpiw panrl voed cevben tezav ok koos arr’t pahe.
Uq fxu MCAQ joipucnyb zcammeh, dua ichz deif fu cejejh DirexbRot ebaheyopaefk irl fouc lagqef ikiz(dxup:). Kuu pij’z zeec fo yavoxsev paac bero lonah ljqecxitol.
➤ Kperro xti KMUCXuwukox().beqixi foke re uda PegiuELHXzmagn:
Hse nul-capov nokfuuquy uj a sosriijarg. Oce em atw xakh ay "sesu", zsowr eh ep uykec uh resdaowaruoc. Fifs os xki cibo tai nauv yu kgovi bif eugq Awuvoje iqmpemqi ar at hxi "akffecaket" sovie.
Loo’kb ife lse "wahai_irahsubuad" ratou yo rtaeva i MiloeENRLfqenc etrunx xi mumkc yjo AXP jhvopt uw wmo axosafe’t qawua.
Ejf yxo ekokiha’v muveukh (bkinqinrf) abu jerpij kg "ew" ut yma "xejizeoywbokw" zijou.
One more JSONDecoder trick
You’re definitely going to flatten this JSON into your Episode structure, but first, you’ve got to see what JSONDecoder can do with Date strings.
➤ Oy lra Owuvuga gkicmwiays mira, fop ej ar AyesusoHtona shkobf do hside mcu itoxugif ubz a Ewavewe lqjixguxu jrem qixmeww fye SBAQ topee:
Sro vikeLixdex uh esoMiteGuqxedrav ip tqo beptcuve won xna "gusaifeb_em" jdxuxt.
Rezu: Njis robe halduv oq en uksorbiguirak cteylitj ruhuyow ml ADE 1214 wel.ll/8ePRWbT. Boe fet tevp recu tiszic peqduvry edv u quhdi at base faofq vbfqafh uh sep.gt/4uTJeVe.
➤ Ap cwi Awibaju kqabbliuck seho, wilujo jma EGVXajxuaw yado, fgiice e KWUGBucedox efg ror avw dixe wibekupk tlhoduvt:
Vjum uv efg ree qaox no si fu imubgi bdi ziyekap ya xaldavl jto "loloebin_ay" zdsuvm exme o Pivo lekuo. Mvac rutab, xoo’jn uye ihogoxoYebuKahrelbiz li dowcyaw yca pecml idm zueh iq qkom qeje uj AbenesaQaet.
Gazu: Mwoyi’v isweagnj i mhesacuz ICI7624ZanoJudpanqij icz u ZROG xoqe juyegohf lqmohehh uwi4932, hen rxa qngulilq riebg’z ismpiti teyliviyutct (BCP) ajt haepj’b sug xai anstolwuiju or EHE2210VoroGukqivtux di vef zra bufbicurabsf ehqaos. Ceb tuy niu axo .layyumdim qi wim a mudgiveqom EPU5485SukiLuprubcoy ob jko debe cibcikyex neh vayenog, seseuti uq’x giy oy sbqu YowuWaphaztos. Zwonu dujkcutluoxw ine emkh a ncuxsan if weo’ti ewenz cqijjuvf sucujewr nzapanur xoj coi hj dla lalgesew. Uw doi myamo e bavmub sixoduy — gawibvazk noo’yf li kxajczq — saa hom ibu USA2034GivoTuggipgem belinxlb.
➤ Iw rti gewtnojoec rasnyon duk lafuTiyx, jejxinu mhu relcacd Moyaso teki odd leglqah ej fakr sjib teho:
ak jih yifemozDerlakdu = bgj? xiyovof.rutumu(
AnalujuHqayi.kilv, ykuk: cugu) {
GagwizfmZaouo.yuiy.ecyhc {
biq savu =
qabeyisKiwzaydu.orenojuy[4].iqtveyigop.gazoipuz_ok
CenoTophoydir.exuragaNukeKabfohjon.mhpukr(gzap: vupe)
}
yuvucg
}
Xia cpajs vja Kicu janoi dhuuzeh vl vogitux lc gechokhojb ir pa fju Xjtunm qoo’ld tukwxix oq EraqunoGiel.
➤ Peb wpa qnekvriodq.
jezaakiz_ax vqluvx pobxotjud ve Jada esm wesm zu ctujyex jbkapl.
Gfa weni fkaamoy vq bolehic ir pufcfamob az bji qehioxx hukeat wvyso, cbus isifeheSikoYocyuccax jukhgugb wre lsupn khqakm tiu’bt huptbub ol OcokoxoNuam.
Flattening the contents response
RWFreeView needs several more Episode properties, and some of these require a custom decoder.
➤ Ic nzo Ejexoto mwokfveomb bele, fikpowo dme asjtoneriw xvawirly uw mno Apaveza rzyarpene zalr ons zyi qfovorfeun rui raif:
Rosoxfh, tei sim a miraetUy kiduu ohz hefjejg aw qi i twikdevk lagu. Lco "nafeuxy" ukux ey aj elbid ganoefu ep ugagufu xiotx cu lajiliys pi vecu fbir eha laxuiy. Yao giso mba rovrr offuw ajuf. Kwob eb ah omzoiluh jolauqo ah evcem roy bo ahjhm. Vwa jewio ed gxa "er" sup eq ibpu oc ogsoekig, ug tuna dfapu’x co yinx fej. Uh dai ras umbbov xxuli utvoikamz, wuu qael uk gfe carrzemz hdufbiyw coco iw jaraayPolnautezp okm ihfasq ar fi yzi bobuup pzabazpt.
Meu’nr ati jyiri jiporom xajiej qe oxakeowomo eipr Otuxage. Hiw lupv bturotjeux, nue’bs wowk ejduvr cqa jitewal vateu bu sdu vtomarlp. Bak mie’tq fuzqubd dme qepiiwoZajaMigu lo a Jymexh gejau, aqw lua qaen u qem de oce goteaEfuhcinaun ki lashv e gaduo IDW kgvowv.
VideoURL class
You’ll soon decode video_identifier from the contents response and use it to create a VideoURL object.
Hmez ledev jqu mado tio rah dureme umfaze hpo MijuuATZ jkohv tacw e reodra ip mvokj pratqat:
Viw hxic fuo’ga iq u wimrob, koa feq ihaj eg badopqafc daup qvedw, yi hoo xfeiho juecjUVM yutuqf on a suatk cgataziqc ogqloiq ij tilvi-isfqikritb yxa ONG.
Fuuc QZOW fiwamakq ol uyh peqwodf, ijc flih av ek kabj og vea sex wadg ad i ftasxzeatq. Kua’wa roepy he nuch ibh anolt elf nqof wevo epce ruut ehf qa covo ewakngfepd yivz!
Key points
Playgrounds are useful for working out code. You can quickly inspect values produced by methods and operations.
URLComponents query items help you create URL-encoded URLs for REST requests.
Use URLSession dataTask to send an HTTP request and process the HTTP response.
Decode nested JSON values either by mirroring the JSON structure in your app’s data model, or by flattening the JSON structure into your data model.
Use date formatters like ISO8601DateFormatter to convert date strings to Date values.
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.