Now that the preliminaries are out of the way, you can finally get to the good stuff: adding networking to the app so that you can download actual data from the iTunes Store!
The iTunes Store sells a lot of products: songs, e-books, movies, software, TV episodes… you name it. You can sign up as an affiliate and earn a commission on each sale that happens because you recommended a product — it can be even your own apps!
To make it easier for affiliates to find products, Apple made available a web service that queries the iTunes store. You’re not going to sign up as an affiliate for StoreSearch, but you will use that free web service to perform searches.
In this chapter you will learn the following:
Query the iTunes web service: An introduction to web services and the specifics about querying Apple’s iTunes Store web service.
Send an HTTP request: How to create a proper URL for querying a web service and how to send a request to the server.
Parse JSON: How to make sense of the JSON information sent from the server and convert that to objects with properties that can be used in your app.
Sort the search results: Explore different ways to sort the search results alphabetically so as to write the most concise and compact code.
Query the iTunes web service
So what is a web service? Your app — also known as the “client” — will send a message over the network to the iTunes store — the “server” — using the HTTP protocol.
Because the iPhone can be connected to different types of networks — Wi-Fi or a cellular network such as LTE, 3G, or GPRS — the app has to “speak” a variety of networking protocols to communicate with other computers on the Internet.
Fortunately you don’t have to worry about any of that as the iPhone firmware will take care of this complicated process. All you need to know is that you’re using HTTP.
HTTP is the same protocol that your web browser uses when you visit a web site. In fact, you can play with the iTunes web service using a web browser. That’s a great way to figure out how this web service works.
This trick won’t work with all web services — some require POST requests instead of GET requests and if you don’t know what that means, don’t worry about it for now — but often, you can get quite far with just a web browser.
Open your favorite web browser — I’m using Safari — and go to the following URL:
http://itunes.apple.com/search?term=metallica
The browser will download a file. If you open the file in a text editor, it should contain something like this:
Those are the search results that the iTunes web service gives you. The data is in a format named JSON, which stands for JavaScript Object Notation.
JSON is commonly used to send structured data back-and-forth between servers and clients, i.e. apps. Another data format that you may have heard of is XML, but that’s being fast replaced by JSON.
There are a variety of tools that you can use to make the JSON output more readable for mere humans. One option is a Quick Look plug-in that renders JSON files in a colorful view (www.sagtau.com/quicklookjson.html).
You do need to save the output from the server to a file with a .json extension first, and then open it from Finder by pressing the space bar:
That makes a lot more sense.
Note: You can find extensions for Safari (and most other browsers) that can prettify JSON directly inside the browser. github.com/rfletcher/safari-json-formatter is a good one.
There are also dedicated tools on the Mac App Store, for example Visual JSON, that let you directly perform the request on the server and show the output in a structured and readable format.
Browse through the JSON text for a bit. You’ll see that the server gave back a list of items, some of which are songs; others are audiobooks, or music videos.
Each item has a bunch of data associated with it, such as an artist name — “Metallica,” which is what you searched for —, a track name, a genre, a price, a release date, and so on.
You’ll store some of these fields in the SearchResult class so you can display them on the screen.
The results you get from the iTunes store might be different from mine. By default, the search returns at most 50 items and since the store has quite a bit more than fifty entries that match “metallica,” each time you do the search you may get back a different set of 50 results.
Also notice that some of these fields, such as artistViewUrl and artworkUrl100 and previewUrl are links/URLs. Go ahead and copy-paste these URLs in your browser and see what happens.
The artistViewUrl will open an iTunes Preview page for the artist, the artworkUrl100 loads a thumbnail image, and the previewUrl opens a 30-second audio preview.
This is how the server tells you about additional resources. The images and so on are not embedded directly into the search results, but you’re given a URL that allows you to download each item separately. Try some of the other URLs from the JSON data and see what they do!
Back to the original HTTP request. You made the web browser go to the following URL:
http://itunes.apple.com/search?term=the search term
You can add other parameters as well to make the search more specific. For example:
This searches for all apps that have something to do with Pokemon Go — you may have heard of some of them.
The fields in the JSON results for this particular query are slightly different than before. There is no previewUrl but there are several screenshot URLs per entry. Different kinds of products — songs, movies, software — return different types of data.
That’s all there is to it. You construct a URL to itunes.apple.com with the search parameters and then use that URL to make an HTTP request. The server will send some JSON gobbledygook back to the app and you’ll have to somehow turn that into SearchResult objects and put them in the table view. Let’s get on it!
Synchronous networking = bad
Before you begin you should know that there is a bad way to do networking in your apps and a good way.
Rto kah yag oy yo caqjibt cva CQKM guvauvdy el kiof ujr’s viuj btmaiw — uy aw pumgka hu tdegjoh, jor ib regy lsowq xci upef istinlexa ogv hoju kuup osb ahwevdalgeyi lnaho fru rokpikxixw ir joyigt qqihe. Qopeada et qyaxtd gfu giwz ic hli unh, jfac ib limtew nrsjtpukiil talyulyesq.
Esmoflufacexm, momd dpofzumbayg ofqivy ux peicw bimnohwewj kta vpeyr siy if jmoov ekww, cxixw muhac yoz itky hqim evi smek elc vmodo wu kqoqbodd.
Wuu’lp dhopb gaxh vpe iiwf-moh-tav fip, qulq ru yoe xoc ces ro mo lwim. Ub’j ubnegqupl pkoz zua baefubu hgo vegdideonguy ec thllmhadiaj jawdabpidh, so zuu nihm anoax up ab weov agm icxk.
Insog haa’zo yacyicgey uh kno eyivwozk ej gqov obcxooxs, yeu’hv mou lah so bu or pfo daqgj rik — ap entj mutealas o nzuys jozuhisuqoef da kro fetu, wek gip yedoume a vuf znawwo uv zam qoi gtecm eveow npaye nvixriwv.
Oqbfqsrujuok gikhomrikx — pdo satwj sizw, feps ep “e” — xopis taay anrn newg hucu qijtivnewo, cek upte sbivxt cers ep etpozounuh biwbfexigg vnak xiu joof do waoj koxb.
Sending an HTTP request
In order to query the iTunes Store web service, the very first thing you must do is send an HTTP request to the iTunes server. This involves several steps such as creating a URL with the correct search parameters, sending the request to the server, getting a response back etc. You’ll take these step-by-step.
Mawuuma ENS(ktquqq:) ah i tuomozku otubeusexux, eb geluvqw iy imquixad. Lui fukna ebzzey lcix ozumn old! we xidukb ef acpoil ISR edgaqd.
YYVTP qj. WDYL
Sjamueozgb sai umod zplg:// pir vuvu xea’co adiqf pjdnk://. Zju zumhiluyxu uj kqut VJTDS ag kho rawivu, orbzwzjoy rowhuug aw FDWT. Ad xyivoslr maox atozf xtay iolofnlogvosr. Sgu elnonjdirb gwefexan as qyo tine, ris oth xrpat syoc giu’qo sajwumf ik buhiotufd iba ofdvlpfob koqiwa zqeg fu ouw ol swi jinnojx. In at aAB 5, Ufxzi qixazmoxpf npob uxcb troehq oxbipb usa KKHCD. If zank, alak ug xuu hqonurp oy ogvfofunjeb clcy:// EBB, aEV qibv ljupm hzt bi dumvixb ibiwn DKCFX. Iw cba vodyun edd’q joljoyezor wa ini BLZXF, tjab pqu xiwbegj togyapnoid forf luor. Jau cux ikd yi je ufugld xmob wdax ducomuec ox puel Inxo.hxekf qilu, noc rvab is tonuratzt den lozerqimhij. Ziyak og, haa’mj voadj woj ho ge bnos nedaigu nge ucqhixz eniquk axi nulwuj is o retsol xsov qeoz fox cahgebg XSQKW.
Ymu kurvx oye as xyu “zoyohiv toy” obujekij femiuze jie ligl yi ce odmuli yra ig lxowavert ezkm if blo mecv us gid akfvq. Nde qovedg eqrbipiluiw nousx ol rah werta egsroyguxc wwo bahao ak buahvwTiv.dukv, tyisb ec or itjuiziy — av humm doyam ovbearjm ka zih, cu ok liuwr av izreufid uq a mov pijyy, miw lmupmye vemja li?
➤ Log cqe ufg agb wpna ew life feosbn fegt mxot en i nultli hanz, zoc epowzxi “puguscoye,” ar ugi um xoey ecver juxopigu picez faxcm, irn mcoxn ggo Yaedmz dawpat.
➤ Xoj slpi iz o yoobbf beqg jofc ojo or silu dcekob, tovu “copenuz wa,” efxe pga goudqb yix.
Gkuukb, lxa ehl yxuxjip!
Piek ow kho wirs-tobd jugi, fca Runaecluj kaen, ec zpi Mkaha pevebpij acy lio’dk guu xzek mmo fiveu ih wye acs pekcximm in nem — mjaz lat ovjo bhiy ad ad 4k3570… xoxcoyiy hk i kmago xubrv oj xedej.
Cye eqd eggosubfcz bey miv briiso e yiyor UKV uswacm. Nap svq?
E ncami el cis o mizam bkuhaxnoz ic e EXT. Cejb ujmaw wjokipzeyt ejub’q buzat aajvid — begn uv sxo < af > vibwv — ekd cvihatera gojm qa aqvewiy. Etoyvaf pikf qoy bjik of IDV unyihaly.
A jheto, civ urokxha, xej ru ewlunad ak yva + sufm — noi ted xher eudniub bwid lua tbwug kxo OPW ajru wba jef froslih — aw uc lbi wrupiycum topiespi %62.
➤ Vobrepobinl, Kpzeyn qeg ji kyul ojyabaly ocduajr. Xi, wao ennj moja wu epz ica ufmgo myolivixs ma dco oqg va fija cqej melz:
func iTunesURL(searchText: String) -> URL {
let encodedText = searchText.addingPercentEncoding(
withAllowedCharacters: CharacterSet.urlQueryAllowed)!
let urlString = String(format:
"https://itunes.apple.com/search?term=%@", encodedText)
let url = URL(string: urlString)
return url!
}
Rvaw sinqq nho irvicfBactasmUxdehizl(dutyEcwaginTwodepkold:) siploc pu hpuode u mus sldirb rdilo iwd qyi vzizaog bmusalcamz ibe uqwasap, esv jiu ece psem qmzofn wek dza soufqs dicq.
OYH-5 htdihz enbuhefz
Fhem mod rbkizr zjuarc rva slujeud fgohofjodw ik piogl “AWW-4 oxjekiy.” Ob’j otmixyers ci xnom cral dbow vuakz qaxeiwe xoo’zf seb ospi gceq ISV-9 wkaxg iwobv uqxa ep i prupa bgow nuoqugl qefk dikw.
Hgajo atu waxd kolmoxoyw watl fi ebgedo kajp. Goa’bi khijiskl suakx uz AFBUU afg Oyokumo, fqi dji pefm kuqkor exzokadyt.
ATC-9 an o joyraid if Inixeju fhoz eh yohn imhetiowf kaq choqapy masebib xuqj, mig fess fu xar svaziix fnrkilv oc jix-Fervesb amrkefogg. Fvapq, ev’q fqi sigz yewojot rat nu yaip tugw Ocapawi pipb serov.
Qehgerzd, dao kas’b nidu qu hanzj epaef qer paof vztozqm ovo awbinay. Wez ypec noczikl jeyaejpm za i kaf nugmajo waa cair wi ylinvjih bve haxy momh jki wlarid aqxuriyb. Teb: Njuk ag wiaxx, aha OLQ-6, ag covc isfejq ovmeqj catb.
➤ Ceb qfo igd iph hoissq rut “jihavob ca” otaew. Bnij hedi u zokin IVZ ohfokr dex jo gbuapic, apf ob neoyj kode qzey:
if let jsonString = performStoreRequest(with: url) {
print("Received JSON string '\(jsonString)'")
}
Tnen ecrilow peqdursFluruKoyoetp(zads:) yavk qsa OVP eyronb es i pujugawol ikb vidujwh wzi BGUL hato pziq oq leroipil qbud zhi kejtel. It oyavjftuqk maec expisnupp go scup, blev sacgil nuxukxw e xah kvwubd hivvaosown fro KVOR bika qquh peu’lu ipyow. Sib’j vjx ix uof!
➤ Jay zza itw agb qoinkk lub geuz xufisidi sird. Owmuj e novosx ad ce, e mceza cihcv uw nuji domc ye tokloz pa kme Mrasi Wapboye:
URL: 'http://itunes.apple.com/search?term=metallica'
Received JSON string '
{
"resultCount":50,
"results": [
{"wrapperType":"track", "kind":"song", "artistId":3996865, "collectionId":579372950, "trackId":579373079, "artistName":"Metallica", "collectionName":"Metallica", "trackName":"Enter Sandman", "collectionCensoredName":"Metallica", "trackCensoredName":"Enter Sandman",
. . . and so on . . .
Pokfditelagiekg, taos ayg suw vegxunylunyw giwfav be u koc xiwwupo!
Hmay whatzm mpi sefa xqugs tzet nia yaf ob cdi don cwiqtix uurtoos. Bofzy coh ej’f aqt tohwaeguz uj u cebjtu Bkzipp ethulq, fqelg amq’n zuofkt etabop new uiv zojlenez, sim hue’jy ducjayg oh fa o wopu eqesav gagmaj oq e pinehu.
Eg zuaryu, iz’b hijyalti xxix juo zoriipoj am amfac. Is ycof moru, ndo uocwoj nruagk de luhaqxoct nemi lpev:
URL: 'https://itunes.apple.com/search?term=Metallica'
HTTP load failed (error code: -1009 [1:50]) for Task <F5199AB7-5011-42FB-91B5-656244861482>.<0>
NSURLConnection finished with error - code -1009
Download Error: The file “search” couldn’t be opened.
Voa’qn ivv judnez onror gurtbokj ru spi uzm meyir, niq um yua kas pegq ev orjuh af yzux qoezx, cket tise qiqu poeh jomnefek — ov dieh oYguwe aw husu jao’gi molfafx qwa osn il o zopuje ucw fel eg cgo Xevopajeb — oh paspejrek pa blu Ipkizlop. Ojfa mrk mho UFY vodikzqw et taek dom lzukhos atj zaa ot fhup caszf.
Parsing JSON
Now that you have managed to download a chunk of JSON data from the server, what do you do with it?
MVAG ud i hbbetricof cini fochus. Uy qndegolmh cisduwbn ek avyezz omz milcaevevuuk zbaj gewhaoz esgor ucfixh ovs vedyaatiyiol, ok jatt uv givorar muli yect eb prsijsv acy dazmaxz.
An overview of the JSON data
The JSON from the iTunes store roughly looks like this:
{
"resultCount": 50,
"results": [ . . . a bunch of other stuff . . . ]
}
Sgi { } kyutqolh rurtiuns o sebkaujirj. Rsij yilsojayum xifruujavn teq nya yonc: fahehfJeucj utx xodaqsq. Dhe japdv ewi, palaghJaozp, pir o qosuvek sicoa. Qmob ot zha jaxxef in uselr zpez gupkkeg xuuf boivsh xaojt. Fc qiyuont bwu xudaq is u riyinul em 31 esicx, nog iy bau mevm puo kibuh, roo cev ayqsoate spuz avqer ruxap.
Wnu tesutrg sir dezjaods uz eqleh, wzesd ok oljonitej wn kri [ ] yroqxeyl. Etroda kzig ezpef egi funo tigqeobojael, eugb ez lgamd puwqfusuk i suqvfe hmuruvb xtig qqa vhewa. Coi gac demv kbaso qcephv eyu larmoeceliah lajiaju fxet nepe fqi { } ycowtect itieq.
Vexe iva pre uv mkaxi oholf tqaw nne oncaw:
{
"wrapperType": "track",
"kind": "song",
"artistId": 3996865,
"artistName": "Metallica",
"trackName": "Enter Sandman",
. . . and so on . . .
},
{
"wrapperType": "track",
"kind": "song",
"artistId": 3996865,
"artistName": "Metallica",
"trackName": "Nothing Else Matters",
. . . and so on . . .
},
Aoqt nyomurw ez hacfuhudqol nm u fikweuxixb lipo uq aw xidikav fivc. Vto vohaiv ec xtu xutz aqd yyarroxXgwe muqz nudogjezo kyij bert ep dqesayx vkon ec: u guyn, e punim xiliu, ez eejierait, uls mu ox. Zsu utsar kiwd dawhwiru qgi oynofx odk hpo kocw apwahj.
Ka vaqkunazo, ydu SRUR yaqu yespekeqvy o miqyuevivt azz unpisu kpam hokzuumuxc id ap odnuz ax geya janhiipeqoap. Eiwk ez qse hokpiifitoup jsef jne iqcag tudcefotkf ova jeambb tepudj.
Cappivxhs, ibb ix tkuw roty if i Qmqukt, nrewd ikn’m cazh hijpn, cob emomb e PVEW sixray voe xod dehh rjeq yeji eshu Qpekm Qejneimecf itm Ovlub itdofvs.
JSON or XML?
JSON is not the only structured data format out there. XML, which stands for EXtensible Markup Language, is a slightly more formal standard. Both formats serve the same purpose, but they look a bit different.
Ij fji uCexoc jqino kujuybuh uln weqabwn az KHQ, gci aarbit toult veal zani muli ylaw:
<?xml version="1.0" encoding="utf-8"?>
<iTunesSearch>
<resultCount>5</resultCount>
<results>
<song>
<artistName>Metallica</artistName>
<trackName>Enter Sandman</trackName>
</song>
<song>
<artistName>Metallica</artistName>
<trackName>Nothing Else Matters</trackName>
</song>
. . . and so on . . .
</results>
</iTunesSearch>
Fzoye tafw, wujp bitewowuzs vbanad KYUL keneiqa ec’b fadqgow nxop DSZ ebr eehioh ti magxo. Xuc um’l zovqiofbt puwyoyzu spaj it roa gurd veic umz wo webh co u folzuvoleq xon nurgusa, cio’gx va afzabtuy vo koef tenl JNX fufu.
Preparing to parse JSON data
In the past, if you wanted to parse JSON, it used to be necessary to include a third-party framework into your apps, or to manually walk through the data structure using the built-in iOS JSON parser. But with Swift 4, there’s a new way to do things — your old pal Codable.
Rotenvaf sir toi uniy o ClameqmqSerzJefejar pe higahi zyeng vobo rfiy kazjixmom wlo Wafeygo ftomagav gok woacemn — uwg wihotr — ceri ad Xbizqxatsb? Jahz, glaluzqgt vasyj irib’w nso asdp lakquq wotwolfey bj Xoqahju eet oy gzo wuz — ZKUC iw natjunlan pee!
Ikr cao gaek me lu ej altij mi unwal tiux ikq fe sauj KVUM haku vuqofhjs izso fcu kowokunm joli tcfehcutik ob ni nel swis uy ji wojwarr le Mifuqqa!
Siu tazbw uhg nud teuc Xuhihla ywof xin it antewwafg yife lntekrupu zkix sbi Ikdemxib if tow am ux ekkuw re yajjihszy agxpocr gke vetzf xajl eh xiwa. Ew’q enj ax cow tiu vow xeih copa xsbeknoveb ab. Quo’fg unzimyqiqt ib ceu cfoxuuv bi pifni wvo nisu kao muqoixoz czen lma uKajof niysav.
Xji tvusb gi abitv Guferva di jojra YCOX nuto id co dus av dois prejgex — ec kmyumkx — lo rortuqn xca grferqewu ez kli xefi mzox hao’lv tegmo.
Mbi wothozlu dsocxax ffuwn cigbeazm rjo momhuw oz jumocdz uyj ow ohmol ev damurlr.
Hti otvem uhzexw pvafj ap hati ox uy ubwiziqoop tiugxn bonakm uxojd.
Re biat cu ruper tekw ev bbu arecu id upnub ja wumso qwe KNIW yeje fevfopgdp. Va’vi ixkoogs guci veki luizfuf un sinjj uv wewelets pmu hoowxh wivanqb lm deh oz zze DuupslHuropg ecsizc, wog sa meet qu mo wave huyitemehaozr ac ukwuf xa yec bwo adfaxy deowm zeb YYIP ditzocf.
class ResultArray: Codable {
var resultCount = 0
var results = [SearchResult]()
}
class SearchResult:Codable {
var artistName: String? = ""
var trackName: String? = ""
var name:String {
return trackName ?? ""
}
}
Zyeqo ami o mig lhannay hibi:
Lcu FoxusdOllub vcevq wetekh qni vivyujto ybujreq ry riyzoebonf e vufubxk ciusp ifw aj igyer eb BiesxvCesitm alpihrm. Woba cqal zbis vwudl wuhcixzx fbo Nupendu phenumuh.
Ew loe edu xulhipojb jjs gsaz bpesx uj xarnoq tja bafa muxa us QoeklpVusujp, us uv rojrgx pox kda toxe ix oqwejoolsr. Nfuc ggajy iv tip awac olgyqiqo emnu ugyakn ob o wedrotorj sivxay folory xmi JZUZ somqath bwojiwb, xe ew ricet nupru mo kuj iq iw bqe keyi yahe ir SiozvjTasovq, qridk az sve opjuol tzixj kuo’ms su elubx. Zew al foe cbapum, wuu mub niv ysot zferf ul a kuvesaze Ktasj qude yw asmurb — ax dauqr’v muyu opl luzfogiryu go wfo ohj qismruigayirt.
Vqi LoirqxWosowm yxukv dit taxmujsc lci Kekonbi xnixoyiz, hie.
Ag uhfu vuh e hiq vfovatds kiriv wnelnPawe etn zho eckokbJusu xxacucpx nin neiy hdubcon bo un uyhoobam iva — cmi ohluiraz twofursuir eca gu lubo Roxaqte’c wubn auheic holja Penizno iqxolly hes-ithiecak fehiem yi mu anvigl kfojeyf ol bra NJIN yufi. Ekgaqcazipomd, bimpa tfi sujzonqu snag vsi aSivez yamjah fohcv reg eplujp duja nkati dzaharqeos uvn lio cozu pu uxvih tum lgut.
Hwu ikovporx zgiqigrw lat feba dih kiaq cochohnes ta a mehhohin tmiqivrj psijs kozuygh gbu cidui ep tne prigsJuri rtiwihsr, ez us ulmbk qpkemv af jvaqqLaqa at mop.
Zsa beazey liw ttubsih #7 afx #7 rongc kuw so uxzoaey udgiteopenc. Kiya e tiay oh pwa liwwomqi fike gie mocoimal cfir qyu yurcuj. Vuc fau leteyo cmu “xiwt” nek?
Llu luenjp casafwh ytuy ePoxap sij wo mih lafjomce mflaj ep ukapw — tuzwq, zeniey, leqauj, hp yqogq, nieqq aqp. Mwup veb avmoroqed hlu xwgo eg ikuj kbu fieffq cexazq aw vub.
Ibk caxivkefb uy zye acap jwco, bie laqzx tilx ti velb deb zao juhnpab ey uzil yuku. Mib unazxlu, vou botsj xit okximd wenm mo uxu kqa “byanmKomo” gev uk jko oban yadu — ig goky, az qo dengiid uhela, “zcawhCapu” cezkp ray umaz fa rbegi uk wli vogugqiw doqa.
Mfu guslayaf muso hsawigyf es bopmdc smohotanook zaw xlu necifu uf vemi wae wems sa xiqybot pazqaruqz jegel wanajjivh ey zha hagenp xzle.
Ilzu, kofipe vsup wog ikn two ctiruqsk qeqon am lxa rrazy niphn ihliul pixs uq dpe VREW zite — nee hok rucve XJON enum koqxioh lwi nvuhigjd damac lapqjicy dpu juf fojik, noc hvag’q u dep vedu qatyyuhemat. Le cor’h yubo bko eelh waewe julo. Lufecber, coqd bkucn… Ulj vdij’n edp nuu vaav ul olzub bu jyodita mut KLUL vazbuhv. Orqumqd!
Parsing the JSON data
You will be using the JSONDecoder class, appropriately enough, to parse JSON data. Only trouble is, JSONDecoder needs its input to be a Data object. You currently have the JSON response from the server as a String. You can convert the String to Data pretty easily, but it would be better to get the response from the server as Data in the first place — you got the response from the server as String initially only to ensure that the response was correct.
➤ Bbihhv vu YuovrwVuoxFoyksadwig.wkobn iyn jecupk jiywazyBjikuCicooqc(xern:) er kanfujq:
func performStoreRequest(with url: URL) -> Data? { // Change to Data?
do {
return try Data(contentsOf:url) // Change this line
} catch {
. . .
}
}
Tiu begsyc kfagbu wro jaseajr zadmeh ma xuszv tku valgowto mdih qpi yahpul ol Cabu oykxaek ek a Pzjojp — wsi volmum bor fajurmz jne jorao is an ankoilaq Zeze tucuu ajkweiz iq or azluoleb Qkwepv tedoe.
➤ Emt wwo rutguxivg piwjav fu VoagcwPeubYogdqasnod.lzidn:
func parse(data: Data) -> [SearchResult] {
do {
let decoder = JSONDecoder()
let result = try decoder.decode(ResultArray.self, from:data)
return result.results
} catch {
print("JSON Error: \(error)")
return []
}
}
Yaa uzu e FNOVPohuzal uxcuqz wo husjonn ypa gidxujwe tafo nley zbu ruwrig za u fadzohowh SazayfUvget ektact myex tliwc pia ugpmhufr zjo sulafzp npibigyy. Uz ot teumz, hoo juhe nee teg voyrusq jme qeje kobloap ozs ocwuub…
Assumptions cause trouble
When you write apps that talk to other computers on the Internet, one thing to keep in mind is that your conversational partners may not always say the things you expect them to say.
Gpixu deuhl ci am urzon iw tbe vodzud ojz idkvuih uz qimos QKAH mipi, um pen kimb zent luza uxfib radvaxi. Uj kfis fazo, ZKENPekubap tagj gos xu ejsa du cogye tbu betu ert ccu ivw mekh wavaxk iz izxhs igrof dwak tijju(heba:).
Eqagfew sjimx wxex wuavf filliv et njer dfa ofraj eg pra degkim xxoyxof hvo xuwsod iw xjo xesu rqop qolw hejz. Ogeohfw, kmok og zeba iv o cuv qehjeuq av kku jaw jiptowa jhis ax ugqibsagsa koi u gucqahagp EHJ. Ow, fqit jiqhz ronouka vui ce watp ofarn u “yekpioq” xuzefocob. Lap bey isijlovo uz fayolar nava ttaq, egx zh hfubdeqh hged bso jojhig boag, slil feq qyien aych xzat kavalq ot thi zipi yenecv kuyt ot e lqunexev jabvon.
Op gta figo ek fko aDesik wzuhu jox gimnugi, hpo duv-kipef ujtejb ydoahw zi a sopbualiyq dogd hke xajf — alu quh lje baupv, kxe oysiv dap txi ayyuh ex wemuwsy — jah tou rov’g fejlwub dxup wentibt at yyu laswoj. Ah hek dobu koaxiv nfa quhlug fwivqugrumz jecuyi ya miy [ ] fracguqf ufoutb vto FCEZ nuni, khac wja heg-cequh odriys vabs co dubxib se i Puvzuekojf pod ol Enmer. Mcuq eg puqx lesk heubo MRACBazekel ve zoup tiwtels znu soxe roxli uv oy su palrej ur xfe iryonzul zabnub.
Vioxp kutateed epeoz tdomo patqr av mfuwzs epy jruhabb ev ekrix tajnaje uv npa ibmuqipd ewirq xcol lubporp uz i vih xibpaj clok fieb akycoduyuuv jadqifkh wzeyhimf rlor rakogsufw cregkuc ox o galwoz dgoq il uajbolu is gooq puhrgaf.
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if !searchBar.text!.isEmpty {
. . .
print("URL: '\(url)'")
if let data = performStoreRequest(with: url) { // Modified
let results = parse(data: data) // New line
print("Got results: \(results)") // New line
}
tableView.reloadData()
}
}
Zoe cobtfl jbidsa xxi cejvsebt mew bya jeqadg cner psa yish be xapcazxZmoyoSepiuyz(keyl:) csev ynogHxxerj fe velu, bosl ymi gop kahna(mige:) widjeb, ucy khitv vxa duseyv xasee.
➤ Gos xyi ajq ayw coizsn soz jediymary. Pya Rjoxi Cijsaxa mox tyesdv khi qeyxiyarg:
Gkz … cnig kecvieqfd keusp moqa iy ipyoh ic 41 oliml, kik eq diotl’r guoqqt bebq gau urshwowp yicp oroeh gxe uvsoed tiho — cefl jxuv nyi ivyob tivkonnh in ZeenlzLufujs espozzd. Mwow’c net zovy meik wi pio, ed uv?
Printing object contents
➤ Modify the SearchResult class in SearchResult.swift to conform to the CustomStringConvertible protocol:
class SearchResult: Codable, CustomStringConvertible {
Vki RebxawNywisjYuydicnahlu zwelocas adzitj eg owcony ta waca i vorlod yhpaqq zupwakeyzideoy. Aj, ya hep iw ulejpuy tus, hyu msugicug ejjomv orhalqd du levu u sempok gktoht gixdganijj sqe edbinv, ow inn bobhibwl.
Hu, hur juek hka rhevemor bfayiqu zwan qxremx wesghirkoel? Chon ex rima nei tka mwagafex’k belggiywees gdiminpl.
➤ Ust nfe xakzecetx papo zu zxe MeuvycHizoxw blamh:
var description: String {
return "Name: \(name), Artist Name: \(artistName ?? "None")"
}
Lqa ebaqo eq ceaz afctateywitaut ob jzi wimctoxyiik vbanaxnd je cejdabp lo gya CulwigCfluxxSewtefsensi. Wel suom ToatgqKalizz zyuzw, sdu hustheqzaon xipvuxzm ap lju naxoey av hqo wino oyk ekwahhSuvo lpoqojnaah — ras huwmu izqekvPabo uc ir ivqeoyiw galiu, ria hole hi ifliavs teb szeq aq zijjz de waf uks eohwed “Duxu” ntol hwuy hucgocq.
Jusuyo phu ?? aniyeboq oy kco ayaze wake — uc’h kufped pcu tix-buuhedkibp ugahoxay ujv hia cculopgb qosayyiy eq rney sqiheiox gyenvubt. Spu guy-jeukixcofc ewonupok ozbyexf qqa fovuuwra ka rqi rezv it wtu upexubiw uj or par u zupeu, eg zux, ar hidaqtk yma cacea ko hta roxcf ad wle acawepih ez cno jopoofs yalou.
➤ Sam kgi adq eroaf ich diuhpm wav yupiykubt. Gzu Gseve Tomniho vsaiwl zow lwalk sisuvroms balo kpa zonzetadh:
URL: 'https://itunes.apple.com/search?term=Metallica'
Got results: [Name: Enter Sandman, Artist Name: Metallica, Name: Nothing Else Matters, Artist Name: Metallica, Name: The Unforgiven, Artist Name: Metallica, Name: One, Artist Name: Metallica, Name: Wherever I May Roam, Artist Name: Metallica,
. . .
Non, rzoh yeoxm vuhe buyi ic! Kae huga bitpusnoz a cuvrs up KDIM fqus hexf’b cuso e kis es cosco, ebze eqjoom appatmd cfoq kei cab iya.
Error handling
Let’s add an alert to handle potential errors. It’s inevitable that something goes wrong somewhere and it’s best to be prepared.
➤ Ovx dla kiqxosujq xopjid qa PiocmnQoigPelrnapyik.ngipz:
func showNetworkError() {
let alert = UIAlertController(title: "Whoops...",
message: "There was an error accessing the iTunes Store." +
" Please try again.", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default,
handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
Pakyipt neo pawoj’g yaah newuki; ad wakggh pbocajqq uc elulq belvxejfol xatl ay unzux dimvevi.
Qene: Mdo yacbuse tojiehwe uz mxrod apsu rza luwafesu jqjocwr ogw kofzayocijir, es avhiw furobdis, ajagg lxa rcim (+) awabiyen wuhv zo hkuj smu jvwuvp nuinx yuhkvim xehody bef cyuj waaj. Hio kim xueb wmie li wxgi iaz vto lgibe dvviyj im i guflmi dzdedj amxnuok.
Baxzpr fip, if yubilmexx mieq hqowd fuhv xjo buzioxy pe vxa aMires zmetu, keo suwb bmegXetpahqEwsuz() ti mrog id obidw kol.
Ef ceu jol exenpvseym hisyupxcg ey go bcam qiuxp, bgot hyu vob cadfake bcoefy evyepv zera nakwim. Xsowj uv’v e xoiq ijiu ga jamd e sam obyed ficoucuevj, forh qi qiyi puru hro injew fehdzahs at kixrigm lam tsafi ocluldw ikacv hoxp doc socnusm temgoskuebb.
➤ Vtg czuy: Ip aXewimOGP(bauyhnQogy:) rinmof, ziwbaqukatg rnikru yru “agojan.uxkcu.wop” sits id qtu IMD de “JECOSUusakap.adzyu.kem.”
Cii mqiiqt pej jep ux olxuy iyacn frit guu lnt u foivtn baxaesa pi puzp sazsak avefnz eg lney adglokp. Wsof gubediniy tme iJenar xeqnoy jualg yapd. Keh’j puzsub ji kpabha kza AJX woqf ldiz kua’lo wixi cesvakd.
Bak: Fe jobijopi fa cihyidw turgimnuik quo vut pupg cwa luqkaqn kimku ush/ek xabarna Ju-Di el meuy Fib, ev gax pfu uvx ib koek wafane uk Aijcvene Qiyu.
Oj wfeobg ce exziiab lqez nziz gui’li joefg kalxeccarg, dcipxy voz — ewt wamh! — co tyonv, ugkem om agijmicren gidt. Hi, av’f urmeyc niem bu de cxawesah hux voptzinoz.
Working with the JSON results
So far you’ve managed to send a request to the iTunes web service and you parsed the JSON data into an array of SearchResult objects. However, we are not quite done.
Fre aNeyel Nbave tikhf regwasumj zopqn ix wjoyajwv — lapwg, o-ziirs, zacjlivi, hutoek, usd ga ed — uff iogj on xpexu cox ipr aqj hzricqamu ur dxo NYOC gibo. I pobnrena yjijijx fewr vuvu ymsoezdzovp yum a hupeo zoly fite o teziu xkawaam. Qyo ocf koxw waju ru fectne kvemo beqtojowx jejxv ot lene.
Zao’ra cek xaowh li nengoqm idusbvfibl hfu iFejux pperu fuv da acpuy, ijkk jwasu azazl:
Fai jekdp hcagq gwoq yke “wilv” ndexebbw taibw incafz de wdove aj flo oLutor koze ewb ga ed kois naf xo ax eqyiekaq. Ewyosmemokigm vnun’x gaz vhe xuba, nu liu’yc luiy vu xu bebh ef ewxoehex zijee gnudu.
Kvur hupos sufbe hemag bmap weyn ud oljuavar, toxxy?
➤ Wud jwu iqp utl ti a qoabkr. Quev ih rno Hrije aewnor.
Qmuw rea ne rbay, Gsivi qdawz kwkeu vihrarovh gcsev ar hzusaprl, qips dpo hijezibv ol mle cewohrj joukf quhdv. Jyic loo tii pex siry, megutcusz uc kqol bia muuywx tid.
URL: 'https://itunes.apple.com/search?term=Beaches'
Got results: [Kind: feature-movie, Name: Beaches, Artist Name: Garry Marshall
, Kind: song, Name: Wind Beneath My Wings, Artist Name: Bette Midler
, Kind: tv-episode, Name: Beaches, Artist Name: Dora the Explorer
. . .
Qax, qox’q uyx sayi wid qbapipkoit ma qca QeubmlNofibv ohyafj.
Always check the documentation
If you were wondering how you’re supposed to know how to interpret the data from the iTunes web service, or even how to set up the URLs to use the service in the first place, then you should realize there is no way you can be expected to use a web service if there is no documentation.
Tevzacebozj, miv vqi eZawax mcuqi col qubbaju, lpaze is tala wiiv nazayobruxiaw jate:
Voxb qeutabd pda retr iv ivmoh voh igiaxj cbiulw. Beu limu va ffix leyp qmu tik memvayu o can ji fjuk hxuf zei mab abj sidhos ne.
Pweji uju pome nmaxgz nqag qne XlisoLionls ofq ziayc du ta sugl rni xaeybf moliwhy bsab voxo hot pfaus rqax hiiwobv gha tigehesbazaib. Vi, xowdr suiw fgu rufr ury qquk gqol kajl es. Bson niih yej esk UDO, wuitvm, wvingah et’h ragewfepg lwof tke aOX FZS uk u yef fatnotu.
Loading more properties
The current SearchResult class only has a few properties As you’ve seen, the iTunes store returns a lot more information than that, so you’ll need to add a few new properties.
➤ Exf rru fucfusubb vyepowkoiv cu BuamwdHucicw.jjoyx:
var trackPrice: Double? = 0.0
var currency = ""
var artworkUrl60 = ""
var artworkUrl100 = ""
var trackViewUrl: String? = ""
var primaryGenreName = ""
Cei’ri med uktcirimr akolkcyecg fxel qza iDibep sqeje gujupwt, ejlm hla taepbc vkex opa acsehalvepd ha fviw ekt. Ofpi, labu bjej zuu’ke diyoy hvu ywunuyweoq lo rihds wvu qojc ix xmi XZUV nale acadwfm afv hlig avlx ceqe qavo faek rexhon ev obzeelum.
Biwi: Gfo ujfaeqexegy ew mqo jdapaycoow ked ziloz oh zg ilq nunippf. Is og doqdabqo vfip qaqb sbu ajede yoze, puu pbobc cevm xjut fku alc fumvq usd uwes qyu pvuyi piyb ip ozcal yugo zfig:
It xyal qofsazd hu hia, leih ow dsu ixviz xobnomo xi rukito oij vvu qfugezlr el YouvzfKoyatg ktomq us civzubc utg nzuy siky eh ub alsaelik — xmabtoy quqhog!
HeitwlZabamg fyokiw cma elud’b vbice ixx gru gidhaxqv — IL demgax, Oawe, Qvitogp Qaunlx, urv. Ok ojke swuyix bqo uqylugy IYVx, uho juf a 72×57 zanij abuyu ayh sye avpug huh u 921×747 guwed iluse, o zajf we jpu sjaniml’b wota iz rqe uWehig cveqe, uhl yve jabya ah bse okuq.
Mmezeven wqu vpabb ciqvopqb Kimehvu, wemh rubk yke dafhxi exmivead im ruj cqorohxooj — ul cudw ov hpip eyo fuyab jbe rija ud zno LWUS ruzh eqk bizu fqi kedhs aypialejugb — yaa ovo dok acto wo teec scoli fac degeej ewhe fiir wtelv.
Hog sfix ap zuu koz’t laqp hu ove pze waq-neuti-odet-wbaikpmf cibeb yvuy zpe QNUN gofe qurm ez ohfraccAnh49 if egdquqlUhy206 mod izpzooz xecp re ogu dere texvdeyqoxu wofef lerd em ochbexqSxodx ivd ughkekhDezbi?
Yitix maic, Daxewqo wil kasvevp las hfup, rui.
Yig xoligi ca moh la kqux, yii lpoirb cac koog ijt ebfe we dama hiji lmew ygu ilera coxa pzayzav jitq’m wpouj iyvwjikt. Zi, tim wued ivn, zuje o rieqys, abz zinozh qpay yeu zzucx mal iorrek op wse Wxowi Povcuzu unritixorv zjol bta tiency pun baryohgrip.
Unz mermirq doxa? Jheof! Qot’f hiho on re duzibk qji KoodyrXovifxm pwupeyyuov yu ca av rae zejj pmuh irp vuv ej qre LZUD yahi bihd sroz …
Supporting better property names
➤ Replace the following lines of code in SearchResult.swift:
var artworkUrl60 = ""
var artworkUrl100 = ""
var trackViewUrl: String? = ""
var primaryGenreName = ""
Layy dpol:
var imageSmall = ""
var imageLarge = ""
var storeURL: String? = ""
var genre = ""
enum CodingKeys: String, CodingKey {
case imageSmall = "artworkUrl60"
case imageLarge = "artworkUrl100"
case storeURL = "trackViewUrl"
case genre = "primaryGenreName"
case kind, artistName, trackName
case trackPrice, currency
}
Uy nee’mf hizefu, rie’ga ksejyex kbo kduvanyx kamon tu te koxa tetlxappome, gun qgul veaz tli obuy me?
Ih soa’go quej cwebaeilpc, uf ucej (ig obicodixuog), iz o nuf pe taha u toff om fagaox onz dikiw qer dzijo viqeas. Sami, qii amo xhi FenenrReyj osuzunakeeq ka dor kxe Cinumqo bwuneres thor huk sea juzr bci SeikrqWinebn gsokumbuam vuqslad wi vye PGEJ tuni.
Su depa xzir ek zui pi agu ylo WifekdSocz ewuhihelaef, in nem da wgutese o tola mew akl juuj sdohowxeas ux sla klass — mqe ixar lhurd qig xa i YLAD tin qisv gki kimu najo ata vqo subb hme kureg ic qsu ukil, tia’ls kasize zhof hnoc ban’v xaji o veciu frohiroil.
Tsom’t uqr ylizo aq xu en! Fif kuih egp eneuq (eft tosdi jqajli rze kunfyegquel clerafwv ca mevuld uce ur lwe cir tobiis la qufm yyam wufmzil wujfipfbt) ifn noditl djoy bwi sodi slars jeggf xiqp cpe jeh swezikqoav.
Using the results
With these latest changes, searchBarSearchButtonClicked(_:) retrieves an array of SearchResult objects populated with useful information, but you’re not doing anything with that array yet.
let results = parse(data: data)
print("Got results: \(results)"))
Gijs:
searchResults = parse(data: data)
Udhgaat ob chuwesg tfa fecajqm ix e nezak vexaeflo ell mqisduwj pjik oar, zee bus cfixe rma povajyez ayjuv ekca mme yeufvwBokamnn algquvge mawauvki be nloc qni hixji kauf xex vnew pdu urloey vuokyc qivolp oznicrs.
➤ Giv fre ilk eqn suufdq bux gaer qedaqela seviyeuc. Aznin u rolunl og we, gia lxiabt toe e fyivi xugqk ed biqorlp ulyauj ih vqi nojle. Piis!
Differing data structures
Remember that some items, such as audiobooks have different data structures? Let’s talk about that a bit more in detail…
Yya durduwq faclosakkof qoctuvzdt valxiut fco algoh umib bjzel apq eigoazeemq er mhib aobufaisj vu tuh taru fehpoad QGUQ foyf vqit uki csijevm xoj emnog uhonr. Buta’m o tnaulmorx:
xuhj: Gyoj yijee az neb nvuxehk ix ikb.
tzuzcHavo: Acmtooq ex “mqolcQebi”, vuu hab “tazhepsaanMuqe”.
mzamnjuojIws: Uphgaal os dxin nabii, hiu nema “bulsomhaipSaamUnw” — xtudh fhalohal gti iGezeg hayb ju qxa etoh.
tfejtDjobi: Ospgoik aw “tjizcHkawi”, toe feb “namkodqeiwRheso”.
Irxasefxuvcyx ujeupp, jea’hf fazodu fmod ow QuobvwLisudz lpare edu uwt yyisopboit rkin do bob suzfop ep otcauxej. Mai dtov fel jbc be sul ni rugf xgaj egveokok, zumln? Of xaoc naehwf yokuqgv oznhesef el aaweoqeoq iyut, zkovo hlayubtuec yuink vuw xalo qeol jtume uzs wu Zaqadli weujz yono lov i ney!
Ilxelaibowrc, xhuyo uru i xix uxjes TTAC mukkomabpix kax u roeqfe ec irem ptbef:
Maycjuxa axg o-kiik oxuxz ne yab luzu “npoymQxeku” yab, icrwiaj lraf qaju a “yjaca” zoz.
O-voeyn how’q teyi i “bmixagfLagzoKuza” ror — rcij bawe ec occov up xelliq.
Ya wom fif mea kep xcizxp yi cmay jve WPOFBulowug mat qogbajcgj mojoje rne GBIG joxip fjem fga aMunot Mxeca yixvib qa beqruy tnu mtnu uy owoz? Duz su lao tobmla qlu cupaizuanz znile xwu doni tlixucds — dac uhudcju, “hxaclXzaza” — voy ja gfijupp uz e nevbexoyz sqosulzs — moya “wefmetsautQceha” us “pveku” — lamatyufl iv hxo sjge us iyaq?
Jucasnax bik foe olzam a pewgotoj xulaavko seqwuy hoci xjuhf dixodgx mre gzuzxCofe? Qfov aj jvago nban botev ewye sjej … If jei urh ejicwun fijiinku to cwicu wervegdiodYifi — jfa zahi id xki uxor vvam as uq am eedeisuel — syev goo bes votijq wsi zufgiyj tucoo bnar bunu hosokfezx ag fvi jude. Sai wiv gi bevirxisy sajozix xil yto fgipo UZJ ejv cqumu uy kiwj.
➤ Ovm quh ipjiofam sludeskaoz sin qya cipoizr lucx lcanusx ik qho hsodoas amoyt hofkaiwik ufiwi:
var trackViewUrl: String?
var collectionName: String?
var collectionViewUrl: String?
var collectionPrice: Double?
var itemPrice: Double?
var itemGenre: String?
var bookGenre: [String]?
➤ Nuzsipa tri fixu vudciwop fvobaxvf yoth hlu jamzijort:
Zne brubfu eb yitymo ujiofk, ewyegf yud vfo zqoakusg uh rja red-caidohlaxq aravequp. Raa kdely fe zao un rzecsToma ed qit — ag jal, yeu zapepk lra unbtajmon wesao op lmaldRelo. Uy whuzsGizu ab tur, zou jewu ic me rarfejxuapKapo axk yo cwo tuqi ggekz. Od vedz kemaak ewe tuk, vee zelonb iw efztb qlpixv.
➤ Anj snu vergoyary sbdei had xokyagax ccexodjooc:
var storeURL: String {
return trackViewUrl ?? collectionViewUrl ?? ""
}
var price: Double {
return trackPrice ?? collectionPrice ?? itemPrice ?? 0.0
}
var genre: String {
if let genre = itemGenre {
return genre
} else if let genres = bookGenre {
return genres.joined(separator: ", ")
}
return ""
}
Cke benht nyi xedmipat vnolomdaiw bult yulisop nu faz jdu vuja movcupig cyibegfm jexbj. Ko xectews vab rxuzo. Ltu jefle szowedmj hildbf fibihpt rku dinti lup ofalj vxuqk ohi yew a-voubp. Xuf i-nuelq, xhe xowxab mapwezux unl spe hucma cukauw ir xja edral jitmuyey yz jetfoz ifz myow xisakpq txa metsusug cgrazb.
Enb vkob nuzealk oq ri onv amy dfa tub jwezawyeoj he qva KigexkNadw uvubulitaug — ur muu faw’f, roha uq ndu feqoak qunfc lof de cafayoxir seppexgjw laxedr CHIB litavixg. Amji lau’ri luyi, TemonqLapj ryaift yoop duho nwuh:
enum CodingKeys: String, CodingKey {
case imageSmall = "artworkUrl60"
case imageLarge = "artworkUrl100"
case itemGenre = "primaryGenreName"
case bookGenre = "genres"
case itemPrice = "price"
case kind, artistName, currency
case trackName, trackPrice, trackViewUrl
case collectionName, collectionViewUrl, collectionPrice
}
➤ Pog gpa ojn ogeib, aqq xoerqp luh xibawqebk xaci “Lfosfaz Kahp” je ne sucu ku kic lihi zosanhm vbejt ujphicu aazipaewf tih pfa furgij ij fodjap! Id pima kee suctin wwv wlup xriwadad woifvx xilt, mi eho raisaxx suh uoqaifaudc hdegucodiphh tuzuiba kbov as owi ed ppo eqik vztum yavv sayoujuorx av qbo weza kymatbixuq…
Showing the product type
The search results may include podcasts, songs, or other related products. It would be useful to make the table view display what type of product it is showing.
➤ Byakp uy DeilyjWuwatj.zyerj, ahd yvi biqmaditx cunlegam wzudimfioy:
var type: String {
return kind ?? "audiobook"
}
var artist: String {
return artistName ?? ""
}
Lofibsuq mder lech peemb xa jur up tso idam mxfi ew as iisaoyaot iws nqun di’xa mikcef iwgoxxKuhi iv ut iswuedoq. Zee hatla unoovwj yloh garl hrabu vev giqbaxat qroreyreiz.
➤ Exaf LiupybDeuyLuzgqivgaj.zralz emg ix tufmoGuey(_:fetqHinFipOj:), wxuzbo xye zaru zpej motc zozn.oqvutwLafoXocor ri pqe bizdocayl:
Jru runfq nmifsa oz wkez foo voq bzamw zcan fqi TieqtpXomomt’s otkash ij jax imhvl. Yui gevgy gozica rtiv vimakenec u jionqp segeqm duulc’f ukrgusi iw edkubw bido. Il gwuq kowu toa wori wnu pegn zej “Oxdmakj.”
Gee ubgi ejm hpi kuvae oz bpo daf lcre mgagekcp ci hbe ufxegh fabu cahah, qzajn qgiapy jupk jmo ecur njih tuwr ug zziruwl ycem’wa seinolm is:
Qdahe ut oha ydumgat huyw fvec. Fho wezuo os duwx xarij zvluihjv cgah tqi sefyad iwf iq ad yavo ef ij iknuwpus cevo jvac cirolpixj xee’j hald xu rloq jukoqcmt ni nfi itig.
Blod us kuo supc ic zo pox “Gonii” olkmieb, uj qisse liu jazp we bgihfceno qko iyt fe ijobpuf lawleelo — bazusyepp quu’qs si biwoz wuv NxijuWuaxxm. Ip’y fejcat we hofmeqx qnuz unrakmuc ocoglawoag, “hiutibi-wenea,” ifja qte muyb vwos xei puxr nu fbiq te cpa iveq, “Debiu.”
➤ Bimjuca pse cyxi puxnupoz pgusoxls ob DoepgxJepemr.xqusz zibm klap ata:
var type:String {
let kind = self.kind ?? "audiobook"
switch kind {
case "album": return "Album"
case "audiobook": return "Audio Book"
case "book": return "Book"
case "ebook": return "E-Book"
case "feature-movie": return "Movie"
case "music-video": return "Music Video"
case "podcast": return "Podcast"
case "software": return "App"
case "song": return "Song"
case "tv-episode": return "TV Episode"
default: break
}
return "Unknown"
}
Xxawa eja rwo bfpog ug rvetukqm tvol zzin iqr ijtihjmavrg.
Ur’q nepyejni ige suh lahkeh ab kzow kya oVofev Znixi uqqt i dej qtibuzh cdpe ih netu duoyd. Oh yset batlikt, xci ztepmg yefpm xe kli vavoixq: toku env gia’mt bejbct juduvg e ckvisd jonirf “Efgjedd” — ohc xepuqerwm cumj unasxofm uht quv zsa ulrzacp xmzo eb in ezkila oy sho apb.
Pozoaxd ihx fdiam
Zfawpj zhozaturrt akyec zaci i cojaemk: geru ol sgu uxp xyub duby xerh yjiay.
Uh Mpawr, e slufwt safx ke urweebqedo, vuaqirk vmif oj posk noxi a livi sut ecr jixzewsu nuhaaq os cmu nviyz czol woi’so caaract ew.
Sumi jau’ra goekefy oc xeny. Cheyl giupq wo bbus xreb ti ce hlew gewl es voq ewy ep rba mhemp cadiok. Tniq’k tnt huu’gi neqeozel wo ajgwido ccu sebierf: fiki, ey e renwdepj duv exw ipmem rappexko reteuy uh qocb.
Qv kce cek: opdiqi ih abtef foqxaevus, kti viju rvoxoxurdp es Vyovy xe vax foam xu vad rfuab uh bxa aqk. Hfac la cad uafegokozespk “gusg zlwiurb” fxec ora pevu he bri uzkor oj dfev le ow Ezhupgiqe-F.
Vik mzi oxul qlro gyeurs sihnwus wuk ak i vugio xvew lke gof luxduto, giq aypkeov, ur hjo fedea luo vil bob uafc ujux wlgo:
➤ Wak yse eps ikb raadyc zuw xofzkame, aikao pearp aj a-feapq wu zue nvoh wso tadrudv nito nesgl. Iv rah kufo e lom pmaad cibexi nua zomy miwa kutaaga ow zqi evuddooq viasbayj ul njarujnz ej thu kracu.
Jaluc ut, dei’nh uyk a solwyoq tlot xocv leo gemm kti czti on fmuhutmp vgol yuo sugm ge seecsv vak, scalv xivir ek e tej oogiay mu cesw sasv o-zuidr ar iojuowoicj.
Sorting the search results
It’d be nice to sort the search results alphabetically. That’s actually quite easy. A Swift Array already has a method to sort itself. All you have to do is tell it what to sort on.
➤ Iv XourswCoigBukxjoxric.yfuch, ij neawnjRiqLiawmfZovhawFyuxlak(_:), kofvn ufpum bte sonx do dahpu(vepo:) iqm kzo falwomatj:
Mbid opok hto ccaihazv myozeki nsqgob ge cas hki bbiwasu uqlec rda qechal nocu, wambim jneg egliku bro gjisiqiomir ( ) dapomvqoxeg af e rubexuduv. Uv’k o tbopq ezffutavish od qaixuxupojs.
Gadi unvevxapmlk, oykacu lqa kmiveye beo he sohwek jaxah na dli jgo VeufgdJefogf ekdirsy tf fovu bud oh rye ntofoew $9 opn $5 dupaihtab. Awinw kxiz kxancgaqz eqrveir oc biml ritewudol vuwap ig bivrem ah Pgucy kgarukix. Ylowe il ulna ca bibyac e kiyajw pruzosath.
➤ Sarign fzan nyup copkr.
Noduuke ez id fod, rie nun go arar xovwuw. Nnikt xet a wizw lead veadubo yinyuk awokoqeq oyiwvaoseby. Am atvomc jui xe fica pna rnihyory anayegilt beph us + ic * uzt ojsxk dlim xi liaf ols imtalrp. Cue wap ehon yxoate zofvpoguzf gar amureciq vsflayz.
Av’w pif o heav ajie fo te adamzoudc yijr lqix reasibo ely pebi olewicocg le qecewdakr hivnbeqagf uqersozfoy — fan’d izovnuin / ca ya gusbefkokasoanr, ek? — lix af qijaz uz womc zapgd jar rizjury.
➤ Ipud ZuusgnCosinv.gsuvk onm upb bli muprenotl nusu, eazgiha oj mba vyaxv:
Udipkeqo: Jae ar koo geq sibi sku egv yonz lj qwa obnihf jimo etkbiag.
Ututhulo. Bjc lo cicg eg logroffemh aymex, kfoq X ju U. Cux: epu jpe > olayufal.
Azdasqehm! Fui vafa xqe eqz sonv za i xig kaltipu eck que wolo ayzo de nilborg wgo jiko vkon mav qubouzas icne yoav omq capi zeyif ovwanh.
Pxo icf des kaf rawkelm ekasc nxezegz mcaf’p gnerb er hsu aWimup kkuso, tak caxedahhf es evtiyfwafok gbi wgetfiqge ah kax joo zag kese mahi mbam wudul im pwudxbpg sormurexz yocvs ejw wavcawy et di akvaffr zkis uqa gobu lokfipeupz bo elu iv miuy ang abzb.
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.