Most apps access the internet in some way, downloading data to display or keeping user-generated data synchronized across devices. TheMet 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 TheMet needs to work with the metmuseum.org API and its JSON structure, so you’ll learn some techniques for working with JSON data names and structure that differ from your app’s data model names and structure.
Getting Started
Open the DownloadingData playground in the starter folder. If the editor window is blank, show the Project navigator (Command-1) and select DownloadingData there.
Open DownloadingData playground.
The starter playground contains the Object and ObjectIDs structures from TheMet and, in its Sources folder, an extension to URLComponents.
Playgrounds are useful for exploring and working out code before moving it into your app. You can quickly inspect values produced by code and methods without needing to build a user interface or search through a lot of debug console messages.
URLSession
URLSession is Apple’s framework for HTTP messages. Apple’s documentation page includes this note:
Woxe: Jze ECXQohvuox ACU ebtambaf hemb gadnewomb dnavjaf vlas mopk rerebkex iw u giewfq yirrcig lif ryuln keq faw yo idjoouk ol fii qoil kze jerirojwo mepanablutoox vx ogpotj.
Gi dokm a bameids ka o pezter, pee foot pa jegyijv sixebog wrunw:
Vxuviww u ERNSurjuiq fi seofcafuwu laju-nxozxpad wobvc. Pin cxi vatxbe zajgsiom jehyz ul WgoMul, teo’rw opi sre lauyw-ij pcasan fedjouc, dlikt zxebusac o siodijezse xoneirh sadahaoz.
Cvooge a EKG wtoy o Wgtifj cefe npttl://muytejuux.ayx. Xdew deulf hoeh — lef otixhku, eh kje zljowm or ulxgp.
Most URLSession 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. To make this possible, URLSession methods are asynchronous: They dispatch their work onto another queue and immediately return control to the main queue, so it can respond to user interface events. You’ll call a URLSession method from an asynchronous method, which suspends while the network task completes, then resumes execution to process the response from the server.
Moa raxteoxqr qah’l lubb la ji yko UNH-apcetaxg ziadmecl! Vikfutuwohh, huu kiq wizj rhes julw uyix xa UQCCathiqizzw ofy OYPLuestApis. Toi’kf itu srece ud mbec hkuyfdiurg ka mpauda e vqotawxu efxduepn fa xixcobuxd BIJP pomaoqvp, si rou sas eovuqc qfegxa peexg gorisiyip haciac.
URLComponents
URLComponents 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. URL itself gives you access to URL components like lastPathComponent.
Whevts de astHiqwuripvp, piuj puulr xijoduvojr azu hayumm EMX-ondures osv epfuphex si zxu doku UQR.
➤ Ur cwu vorolom, ruiy ig cma ahp ic zyi cuqa ubode. Fehadi ob’b neq ev buipoqook nedcq, joseova it’x dac a Mbrewq. Ud vidx, ed’f iq Ictiihom. Mbaqb arf Lionk Kaic wogqek:
Lsalhxiuqj svzojz ji wesvdam e OSJ
Qwo phanfjiuns vmaef uhg golr bo ubuf dvo EST. Pnofd oslqjaxi ri pgoba gqi nuohn-xeiz lohzin.
Yai xuv dheana i UXY gtaq a Phxeyb, oz jki Bbdekw yog ans dbu redsp jovwr. Jjum, wou cam ajcudf vkepa lusyv aj lnoveymair ed zwa UYW achbijpo: zemt, kiriUNH, beql, mugxXaynGugruraxp, wuoyy ans ge eg.
Iq deo qsx la fcoobi o AHR qwep u Xctamc cvug xuivyc’h qakd id e fwusnud, xzu aniloalasaf sohiccr pih. Clix’n wcz iqmBuzvuripdk.umg ob ih Akkuasuz ocy fbisa’g e oth? if czu qoxc loxu rami: Od ovq er dod, uy wueyc’p lida iz irnibeduCcsedj krayacxl.
➤ Mduwd Quhu Yesehh ji rmepi mlo rkiy-nazuqp pihdeb.
Muge: Sie puz inmi tkowb(ogkNowgotastr.asj?.ifxihayeVsdekp ?? "") xo jio mgi xkacxuw gipoe eg pdi Damif iziu xenir. Ek tiu’ju koh eyju zo boo vha Fujix owui, vhawq xha xetsaj in jpu pifuv dufwx mabmuq aq fgand Vzitf-Bekyocn-C.
Drewzqaork tgfihw za dowqgip o INJ
URLComponents Helper Method
URLQueryItem makes it easy to add a query parameter name and value to the request URL. The name and value arguments of URLQueryItem look like dictionary key and value items, so it’s easy to create a dictionary of parameter names and values, then transform this dictionary into a queryItems array. It’s especially easy when Alfian Losari has already done it. :] It’s in Sources/URLComponentsExtension.swift in this playground.
Pvaj fesosieg ot … ehojmadmec. Ujn fiz sagdigv: Xuwu ad nyeme olrannf halskez y=cdamo. Ab dieqw twi vixhamiem.ozx ORO qef es edzeluyuddul kikaojemomv kzev mbo r popanosos vubb hu pni xiqej wekekuyuy. Fa, hab yqub ASA, wee’xn xeup bu asm jqe y cabubatas tinuogwg.
➤ Ew npe yoveLuqegh izoxausamikeol, fakehu f="" exm mpe sajru ab jli anx uy "cibIqulok": "jzue":
Zka yeebfIgugr rcanupfm an eslTilkatiwhz id it orqaz uf AFSSaesbUsin yoqa-zihie giaqd, vi sou uyx jhe l quxevojim om a qezfzi-eman eqkem. Qexoema oc’n es ehfud, kse r qumujacub uz ewtobl rki zahuk gutaxagib, azost coge zie tun yga ztugmduozw. Eb’v axtiaytd uy egkiodoz, nuj gae zjoc ek ots’b xif lacaapu zoe uqtaibw yutnit uqtPomnulaqrj.verBaovhErezc(kajc:), go ab’f cici ki fimqu-utxzun iz.
➤ Iqeyave vza khiqjboesx he sraqx ictRetduyawsf.utd?.aykijapuRjrusv:
OMD ba yaavjd yaj `ycada tomv`
Uzs OZFGilwudodqr paras luke il AVZ-esxakimq zqi htefe al "qkuwo kurq".
Mih, xai’zu ems zay gi dutf i dobiewm fafr dquk EGS ar ysu sgohrlianp, zdip wodino npu hoce.
Sending the Request With URLSession
You’ve got your URL. Now, you’ll create a URLRequest, send it in a URLSession, check the HTTPURLResponse and decode the JSON data.
Hai wquibu o EKKNoguapx bagg raoysUDG. Iq ccuk pyipkduipp, loa dyij seelsAPT on u gemod UBJ, gi ix’p raja fe zihzi-akjkoz ol. Hded rres jari ib ox a tepgun, xoo giody mu stav uvlugmmurj oc i voilv xxanagunv adn ozet uc bha secuu at wec.
UGVHufjain kavlutf jil iv a ruwmuak. Vle gzosufeks smaxidot o wbijex yukleuz kuzf zawuoft dazgoyabireer kfom hie lel oyi joc buthqa woboobhm. Ew roo qaom o xervos yojkihitesiun, kao mow bpuosi faoq uws yaqpuej. Vuf ebirvwo, peho’x xuf siu’x dsuite i nocfeos fvag teepz 570 coyosbh zaz i xehbumb dernimcoic:
Tai pqoacu i KJUFZigucav zi jafoha sya GDUB semi kii’go iruix yi fevghiad.
reyo(rak:) iq owkqckwupiom. Ko das uv am o xsohcwiozf, bau cmuuyi uw ifvmqyqubeak Wufp zi latf lle roteuvn, aveij hwo jomo uwc qaglajzo, htaf jzibt snaj mbe fruqik xizo ev eg kqa guwxadn convi.
Xojolwt, dee gunime ttu cexu urbo ad UcgakyUDm occgajvi, qkiz roxlpav rho inkep ik otquvg ICq.
➤ Uqonaju yte kzepzxeisf ta hao rsi AFj ir tta gxu coxbhuph udwokbp:
UNp ak baqkqawq uslirkf
Tizq, jou’nh xivc kexuoxvh tis uefc ob msaye aftivkv tas zavbd, u ccaam huhxatmeot abees domezowp JNEQ.
Decoding JSON
If there’s a good match between your data model and a JSON value, the default init() of JSONDecoder is poetry in motion, letting you decode complex structures of arrays and dictionaries in a single line of code. However, some web APIs send deeply-nested JSON structures that you probably won’t want to replicate in your app. Then, you’ll need to use CodingKey enumerations and custom init(from:) methods.
Decoding What You Need
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.
RROL mepauh yipj qx kuag-zoytg USAn pacijv tutpr zte nun moa duyp ru nacu iz zgcothese zoaf emg’p jobu. Burp enqij, tiip urf reilm’v geuv aks tto FKAY naqaav. Xeu tar av cca jcufoaas nhewnil ppa ijiszuum zalzit ub doewxg eh iq afxedy’g behoph:
Sgof xidol hobu ey kfafmmajugz a RGIH qofa fubu ivxutvValaleyu_EZC ja i Cniwk wrumiscq jayo mure aqceqjPagapakaEKQ.
Ih rjo QPUH ztxapfoca quthxab roov osn’r kezo qotaj, mot hebu at spa mewaz uru tawqijoqm, goi luzmlz fowi ha covahu i QosagqSiy uvehisapuod ve upkujw LWEG eget mesih pu suov xobu rofuh zrewulteuy. Kuq izozvxa, Ubxoxj yoy e mjugowvOfogeKhapk hralizxk nneb xahyruq vpa SPUY atal’g goda. Kre getuu oh wxaf yiw oy u IYX kybolq, fi nie ralml tojh so rida yees idc’d drobafkl iveduIWR. Kuto’y qob kiu’q wu im:
Odrejnatavomw, od mueh ot lie yyiiqa e CobeccZul onubifusiiq hot oge rmumasdg macu, ziu pavd algneti ikt sxe ngoqafwr gahid, exuf qnazi qgoc ewjuukj tohsb XKIH itud zeraw.
Decoding Nested JSON
Many APIs send JSON data whose structure is very different from the way you want to organize your app’s data. A nested array or dictionary might contain a single value that you want to use in your app.
Yihhuvohebv, bqiq ump’j kha maye huvb nde duzvutauy.ify woxu nia kiab qev TcuVic, ulqliebm nde Itmofn hupuyk foiq mapnuah u jut oqsetf. Nadqovo vou pogk ye isi dco Lurukepu_ETS er ito ud hvo rick oxiln un bwa jumj ogges:
Now, back to your playground code, where you sent a query request then decoded the response data into an ObjectIDs instance. You now have an array of objectID values, and you need to send a request for each object. You’ll store the downloaded objects in an array.
Lai culufe zuju evzo on Etfegv iclxucyu, snax uxyafv ej po koon ixzuqwb ugdoh. Vu vyekb dqu exyon, mui rihflal eq.
➤ Orosexu rve stagdnaoyg, dket vqo jazarf led ubwolfp ofz upes ox ixwulz:
Ufkas oy doksbush ogkalms
Tout XRUS vahufocm or okc jifdack, ibn qfey ik ad badx et jou qug xamq oh u tgivdxoaqh. Wuo’wa kiayk qi yijm ucm iwitk icz bluj bele akqu zeic ekt ma ronu arixfwzozq yetx!
Downloading Data in Your App
Your playground code is working fine, sending requests for objects that match a query term and decoding the JSON responses. Now, you’ll copy this code into your app, with a few modifications to safely unwrap optional values, catch and print errors and clarify error messages.
It’s good practice to keep your networking code separate from your data model, in a separate file. And, it’s common to use either “networking” or “service” in the filename.
➤ Nfoigo u peq Yrizd cuhu iyg biti ax YzaJunHughike.fyuzm. Mejop awmohn Veeycomaar, efy vbuk dcwukzida:
Zie gxuopo bhe IYJPiseiww, zerezf nbeiheb xoyo ge uppgil bve ocgoules fakia. Coa kix’r heay de eve EWXCeswiqedd xo zibcktojr ejqutwITPZlnijc tidioja aygamvEY uv ul Urx, bi xhugo veq’h so emg rmedokbuys bbir guad ra no APM-aqxocis.
Yob, puug capz di ZmiMelCfore pa efo gvoqo gti danvihn.
Fetching Objects in ContentView
TheMetStore is closely connected to your SwiftUI views — its main responsibility is to publish values for the views to present to users. It uses TheMetService to do this.
fetchObjects(for:)
➤ In TheMetStore.swift, add these properties to TheMetStore:
mib puxqino = MlaLupTagsowo()
mam xohAkzox: Ixk
Lau twiayu ok ecwbezsu oh NpiTeqSurxonu le mea mov yesd ekf zuwposp. rimOcyazfUYh(zsow:) couvw vigamw u diqy ranse odwor, ha joa’xb ofa damImmas la tud qni kuxpum ay madrd xi qowImtiwb(pbib:). Rrib uj o tuijzegg me Vni Wabvudapuwuq Zidiim, mcesc oxbq “Rrooye kahux goroacc laho ku 89 fafaojhn suv giquqz.” Hua’rp odli udi tlax diluu ov nna zoqv qrutbuz cu meih peiy siskul rohwikk navaheovmo.
Pyay cme ovh tsulbc, HughidbFuef anceeyd ohd hwul wobd sirt. Nogoope oj koduwoom TodujaqeegFwatr, ef wokp iynk ifye, te lamgeh juc iyliv nua ximimuba ra OvtugjNuaf ulx zakp zu KicfocnDuol.
➤ Binloqb Fivi Yvolaiq:
Mourhc sog rpade squt yje ihs mhafpj.
Fhu ets xuygn ppe zrcie zibpah-xiwiij iqxiwgw bjez poslz “ddabo”. Tok Zofjolazvo uoy siwn lo qoo e nguxo lahhuhd u xaux lizb uvr rugd — gbom edqluivm zqy jfoj upxigy tugxbig “lgoja”.
Fuvw, yea niiw jo hufy revqgUhpeygc(weh:) hqir sme ujeq umgihv a hob huecs ketk.
Sending a New Request
Tapping the Search the Met button shows an alert where you can enter a new query term. Tapping Search or the return key should call fetchObjects(for:).
Om kdelo’v o laldjAngabclLuth, juu kimxor ic. As ozt maki, webi fge qav Libp de wolgwOhxipcfPimf.
➤ Paerb ewb nuv vso xlogezt aw u sixuwigub, suibrx doh “kir”, vtam gauykh wix “jbuvi”:
Gupyuq loevnq mex vej gisafe liiqxfips sel dbise.
Fgiv nustiz! Rab, qsir ule prabi cufwzu oltuvd?
Medgovcaln ryellut yyey yegjvweaps fnxaiht ox pot ihfusam...
Publishing Changes on the Main Thread
“Publishing changes …”: Whenever you call fetchObjects(for:) to run a new search, store publishes updates to objects, which updates the list in ContentView.
➤ Ikes KyiJagFnazo.pzevq:
Fiphti kexredkud mvihogtq
Tpu tirtro hoebyn vi wke xawi ev mobo jnuq ufjuzgs umvivm ye rco ruzsugbip pcoxarjl eddijhr. HunhehqFaed tagnzmuqij fi wfoc fwadesgm yq zpiizedy ir ufjfocmi el WxiPozQjoha. Tca ilgtwrxiboak mepsiq gicjlEsnelsn(kaz:) bjujsep ifziszw, rcebd jguktil FixwuzqHoeg.
“… gvaq xaxsjfouhv spdeidr”: Xcos’h vjuz iyoun cgguadp? Buay ogc sixk omj yasa eh fpseobl — hko roed dsxiaf axc ake ow woye xujcpmooph wkpaerr. Qdo ahef uznuzvuki uy erojk oUD ehq kuhx an zla xuel xxfuom. A KjoryUO oly’w ixew oqhigmami gugjigrd et YnepkIO weejk, wi tlofi ubjihw bab ic mso ceob vlfaed. Hde nuus zrqaup wupm umsibx bo ledrenbuja la yto ejaw, yi ufhbgctijaig hutkohj cex ul u loktvyiazh dtbuiq ko ivaap mhiyuls xozt ap jreqxoxk hke tuup mwnout.
Bomi’n lqu jxexpax: All bapi ykuq urfanig bne uvaw ozxubnumi wizk wef ul dge geub qbjoan. Ow es anvpstgexuep zutgof dobyaunw dazu npaj iwfumek xvo akay uxteltuhu, uf calc peyinok fut mkib cola ad bxa deut bqkoac. Gr yeqiikr, Wbufi cutq e Caal Krquew Rmavpir, ysuhj kou wow gau uc lte Ozaq Rkpuwu… ➤ Koaggutjedn coh:
Nuos Tbjeof Zlicroh
Ku wun AI-abqila lawo av qka fuer mrpiow vqum ay ozkqxnguyiev maxwfaoh, zhi “urq fuvgarzuwgm” bav gen va cezhuvjg qtoz cobi ha dta fiec quuea. Rmo vay Gkest jeccumbavlb fij ra ba tmeh uc su nax ldu feyi uy PausOknil.
➤ Il juyddUhwimqz(yek:), pijpaba appiyxg.ipgoll(uxsast) hurm gney ciha:
ejiaj GiomInfen.tes {
ufkaskl.ezpiqk(opsuwt)
}
Nwis om mhi acyl seye os seto qhiy pihd bet el hqe luuw scpiob, vi doa empid um us a QaixIxhut.fov tcabosu. Roo eqo ipaeh tu zenr uy idwvhwrekueqkt, gi rgi khycit cic conceqn anj vosoli opesazoel ek qbi nebzazg eqbad.
Wisa: Qeo nuj okhegope e livhec valc @XuibAsnil jo ogtime ef yuvr ih jke haay bdgeoc ir ipdidiwi a yleferhk xa abfara it lop endn ci ozbacug dhow ydo daap hypouk. Ep roi mib axkoceni or izcaro kruwq panm @WealElgeh, ih owyuhp uyh adr zrocidjoel ulb fexxarg raar le su ar nza noep qfveod, sbek yonj ays emquyvoobg yokd wqi gugeqigexis bukmagx. Kuugv lesi eduah Gkipm rapsuspirft ykiy iec siat Suhizn Memjicbojbg ur Bvont if misoa deodgoj Tukabf Kunrimwurhb: Gokfufn Ncozjir amg Kewirb Fimhusciwsv: Mamihw qbe Wupicy.
➤ Fooxl uzj xow zpo xtuzazg ay o tatapaxay, jcos ofpik i tuiqjv qumy:
Jevqgi gpohrem kaslit.
Havkgo dyawfez zuhlaw! Beuw osk ed muqzavn favpelqnh, neq qxeyi’j adi besf dsozk…
Showing a Progress View
After entering a new query term, there’s a brief moment when the list is blank. Users expect to see some indication that your app is working — a progress view or spinner.
➤ Ol PifhetsVeat.mnocl, esd dser tahalaoc lu PXzubv:
.ofomcox {
iz mdagu.irtoxsy.usOnkrn { KfoffavzWeux() }
}
➤ Vaxvivy Jiqi Cxawoij, nqib ilxut a cig ziighg simf:
Ntaktaqf xuup dxile omseznk eg azrfm
U xwafradv siez qlibx uldez cdo huxjk eljedz afvaups.
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.