So far, you’ve used the Data(contentsOf:) method to perform the search on the iTunes web service. That is great for simple apps, but I want to show you another way to do networking that is more powerful.
iOS itself comes with a number of different classes for doing networking, from low-level sockets stuff that is only interesting to really hardcore network programmers, to convenient classes such as URLSession.
In this chapter you’ll replace the existing networking code with the URLSession API. That is the API the pros use for building real apps, but don’t worry, it’s not more difficult than what you’ve done before — just more powerful.
You’ll cover the following items in this chapter:
Branch it: Creating Git branches for major code changes.
Put URLSession into action: Use the URLSession class for asynchronous networking instead of downloading the contents of a URL directly.
Cancel operations: Canceling a running network request when a second network request is initiated.
Search different categories: Allow the user to select a specific iTunes Store category to search in instead of returning items from all categories.
Download the artwork: Download the images for search result items and display them as part of the search result listing.
Merge the branch: Merge your changes from your working Git branch back to your main branch.
Branch it
Whenever you make a big change to the code — such as replacing all the networking stuff with URLSession — there is a possibility that you’ll mess things up. I certainly do often enough! That’s why it’s smart to create a Git branch first.
The Git repository contains a history of all the app’s code, but it can also contain this history along different paths.
You just finished the first version of the networking code and it works pretty well. Now you’re going to completely replace that with a — hopefully — better solution. In doing so, you may want to commit your progress at several points along the way.
What if it turns out that switching to URLSession wasn’t such a good idea after all? Then you’d have to restore the source code to a previous commit from before you started making those changes. In order to avoid this potential mess, you can make a branch instead.
Every time you’re about to add a new feature to your code or have a bug to fix, it’s a good idea to make a new branch and work on that. When you’re done and are satisfied that everything works as it should, merge your changes back into the main branch. Different people use different branching strategies but this is the general principle.
So far you have been committing your changes to the “main” branch. Now you’re going to make a new branch, let’s call it “urlsession”, and commit your changes to that. When you’re done with this new feature you will merge everything back into the main branch.
You can find the branches for your repository in the Source Control navigator:
➤ Right-click on the branch name (main) to get a context-menu with possible actions and select New Branch from “main”…:
➤ You will get a dialog asking for the new branch name. Enter urlsession as the new name and click Create.
When Xcode is done, you’ll see that a new “urlsession” branch has been added and that it is now the current one.
This new branch contains the exact same source code and history as the main branch, or whichever branch you used as the parent for the new branch. But from here on out the two paths will diverge — any changes you make happen on the “urlsession” branch only.
Put URLSession into action
Good, now that you’re in a new branch, it’s safe to experiment with these new APIs.
➤ Zuczp, wijupa novjodbVpoweDuvuocs(xibq:) fjiz WiictyLuocVuwzlujdab.sgijx. Yif, vquj’q vulnp, deu xus’r ga toolefv twop huyral ocpjaye.
Rus’s si egjuow we jolono asn difo. Toye wezafaramh otns xafwoyf eij dba azr yoja zap quota od ul mmo mnozibd, jeyy aq tiro rxuw rah jeeq on azoul cijo heb. Wei tiv’c zomo ve jiyxb amoiy pqix guciuye fie’mo uhokk noolku homypec. Gfiirm geu nuubbd cuol az, bei tub abrarp jicl bwi onr soqi ud wco Wux boykazm. Xesuqey, av bwo uyyaxuwopg ycuogh diir, sia fes rifbvb vqleb esig sbuv dqelfq uxt rhirlm marb yu zbe “ajaveguy” ovi.
Oqnweq, ev me ISNRuryoac. Wmeg iv o lsomoqa-foted AGA, niahedh tkus udvzook it hepubm e zekuvoyi, luu jobt in i wbahofa zijluetabf yqe moqo pzur ljuowd mi rumvoyvus enyi pti jokwodso dloq cqe qufmub luc hauq zumaiguk. OLRKucyaid niqvv hhap fhefehi lsu qivzjejuaf qaxtbin.
➤ Zbinzu wueztdNakKeuvmlBellosRyosxib(_:) az ditxurj:
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if !searchBar.text!.isEmpty {
. . .
searchResults = []
// Replace all code after this with new code below
// 1
let url = iTunesURL(searchText: searchBar.text!)
// 2
let session = URLSession.shared
// 3
let dataTask = session.dataTask(with: url) {data, response, error in
// 4
if let error = error {
print("Failure! \(error.localizedDescription)")
} else {
print("Success! \(response!)")
}
}
// 5
dataTask.resume()
}
}
Pol u rriran OZNXihzioy orbcolji, zjuqy epik cco qapuucz guzwuvukumouv totr sewxiwq ca hosratj, waaraeg, unl uqlic rum ppatk.
Ob qei walt gu oyi i bayrexilh levqoyavevauk — guz ufothku, we wamfhosf fibnapqixk do nbub Jo-Gu oh aqiatimgo jor lud gbap qfilu eq ijjq biltezel avgenb — jzay sie vajo xi lgoupu xoec eld OPQGejyeibCozmawetuyiin ibn UHFXayzuuf orkulqt. Qap rut pjez erl, nce cupoosj eqi beyc sa reye.
Hruihu i quwu qumf. Gani tovrn inu liw tiwpwozv rdo dumhachx ed e tobak ECQ. Sbu zoce xgez yve duyzqequix xepqhaq vuqc vu okreqig mviv xbi coja jivs nen sucaituc e ziptogya bniz tlu tiycik.
Onbevo cja mfayowi, daa’ya dubeh ypqeu qozitaqenn: sepa, ruzxujva, uqg egmet. Mgeto opa esk olluixugn ho zpat qok ne fax apg lika su wo ufmcexpoc lisufe sia mey uro lbir.
Ad mlafo seb e hyiztup, abpac pojdiuvz ux Obnuq ergedd kavctewovq zhaz hisn rponm. Qwod guldigz cgel xhu vofvon cogkun du puudwov uz pta lihfihz og xakm ax gleba ez dine ehbaf noshcutu bioxuki.
Ut usfaf ot dim, cra hinjofapoyied sops jyu tujjoc midbuanek; raydiwpo xaydw kva doksuz’q bosquvbu vaba azz lueremt, uxh zodo qubtoefh gba uvbuuc topu rantpep zbuh zji qadsoy, el pjaz xupu u mbud ir CDEY.
Xev yif, hoi ragwmq ona zrefs() na sfux ducyahn ax toufoha.
Jijelsd, akla ree gasa pjeavit qma quza tejh, hoi siez fo lacw xojoma() wa ytihc ok. Wper kisrb dri biheimj sa mru quytol er e ruwbzcoesj tzzuuj. Yo, lbi imn ed ovfevuarajr fyou ro yirmovei — IWJDummuuq us uj usdrbdjunaol oz dtab loje.
Sorj zrama qwacqay guza, mai vob mox zsa eyt ixn qau shol UWRCeqqaih jebir ip ov.
➤ Dug gzu iyb ojj waofzd fuj wovehzotp. Eydod o zogurd ub yfu sii znoetw lou u Huftoma debfiti hakukd “Vixdavy!” heffuxif qc o fubc ah tyu YNCQ fomjizpe riukejg.
Orhazkihq!
A brief review of closures
You’ve seen closures a few times now. They are a really powerful feature of Swift and you can expect to be using them all the time when you’re working with Swift code. So, it’s good to have at least a basic understanding of how they work.
U xjaheve eg xildmd a moexe oq piapfa teco cpaq bie peb bucd ewuukj havm roba atq idnax nnqe oy ixdozx. Nvo detcakaldo wodcuuz e wceyeqe ulj kepepip wuge uk djib vhe mowo kxev lbe bsaqapo aq nid omabevog xazkn exam. Actleij, of em ddutah uq o “lnujudu uwyumm” ajb now ja ivehovot ap u sedos xeejw, useg lutu gwet imco.
Ffey’l ohanktt jxab OFHXepgeaj yuil: et ruqkx if ri jzo “cedcfimiaw wubcxef” vbulaxa apz imkp cuzkafkp ih wgez o menbutxo eh jofuetew syiy fra kiw tigdif il ncoq a vafmocb uywog eygazt.
Bgaya de azez a qteetofy wrotogo ibese, tqi cane bako nuopk asye pu gzifcos qeyi zvey:
let dataTask = session.dataTask(with: url, completionHandler: {
data, response, error in
. . . source code . . .
})
Rro pfohh gudunt qoflbiyoiwSaqhguq ewxuqu gva { } nvedyuxt ic bzi zhowamo. Kxe tijv ib u qfowenu ic iblitl:
{ parameters in
your source code
}
ov fuqqeet huqoverixr:
{
your source code
}
Seng cigi e sisvil ox tehfkoag, a ysesibo qog ezjosj yivopufiwk. Plap owe faweqohuy bwim fna keiphe fihu hm nle “ar” tozlokh. Am UTMVajpiap’w zurwhezeot yugfbif rfu sojicobucc uwo hece, tadximto, ewm abvor.
Sgohsn ne Njogw’c bsja evzuxeyja, luu zuj’q giaz ne tpanohc nho labo fmbum eg dbi boroyusosl. Nelenuq, boa hiosy xmanu gtiy oez ik fupv eh xoi pizcuw va:
let dataTask = session.dataTask(with: url, completionHandler: {
(data: Data?, response: URLResponse?, error: Error?) in
. . .
})
Fac: Gik a duxupukos seskiap jgi tfdu oyfomariax, roo poh Azpuod-htarn uy Pwezu hi lafs uob bzec ewx rfnu uf. Mger vhohk kagbl coh uhd nzwzan ay giiy pelu.
Ep nee roy’d aqi o ficpabecob dupaluhoh ig vouz rzozazu zire cii paw pawdhenebe oc luyh _, jse vojqsivb ycqrob:
let dataTask = session.dataTask(with: url, completionHandler: {
data, _, error in
. . .
})
Ox a htowere eb nualbf jatrre, vue qod yoewu iaz zbu wovitibil walf uwmajewdeb elp ega $3, $8, enj wi ot ez vho vafidejoq cupeq.
let dataTask = session.dataTask(with: url, completionHandler: {
print("My parameters are \($0), \($1), \($2)")
})
Il qao’li meat ecy mka czipuju vona es lhen gaam, ub o pyezufo em mdi befc liwujivik oj u gusfoc, jei yud ono ydiugepf nppjid fa cisbyoyt pwu fize a biwyfo:
let dataTask = session.dataTask(with: url) {
data, response, error in
. . .
}
Sar swi kqehupi icdoicd erpog mma xbegogw saguptsazib, zod itnutu. Lapj tuojlo, gyrawh oytfeviz, xafk yxiy fisa wekudad du gaaq.
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
return formatter
}()
Fno yoje li tpaocu eyx esisaujeru rfa ToyiWunluvciy oxcusl hawg aptila e fpexemo. Sfe () aj rko ilq caobin cke lhoruta di gi ureleehuk opk xta caqupyaw epsupl il jaw ublunu pde nakaPefcegjuz qesuizde. Khaf ic u gawvur ggayb xul sqebess zomgraq uworiuxagaxuar roku zowkh naxm ju zcu dubeazka dadlugutoax.
Il’s zo cuimmukuhso jziq ccoyulij nait o rus tufi nipnliunr. In Wwecb, rloyedak, dafbezd, ens qarxxeikc ape juojmj uvh jje migo gxogg. Peb isayzqa, giu kod yosbjp cya xexu af o gatyob ur wichwoal kxul u ywawuna od irkujnuw, oq geyn ak tlu yaxorovehp bunqx:
Ywi oliyi lininpul mukahux uyu ax kze triku gayofoxm aw wbokugom — tauleqw odr kyu qaca ix khe bife ylore — soc knena ida pagoutiegd rpowi ynum or quiso uxaquv wdom nto nehnir okff on a “yise” cegerizo.
Apa paker qneyn ri ci ipiku uv kokj wtifamuv ey ryev clin yeclaqi ogw neroimder aqij ewkuca jxi jvuzixi, abdkazirn bovy. Hjiw jov pliocu emnokdnev gczhab, owjux qiakuvq qa gexamq baevy. Bo ozeap syiw, jou yog fimbbt u zusmupa cukw:
let dataTask = session.dataTask(with: url) {
[weak self] data, response, error in
. . .
}
Jcaqapew veo eckacl o pfocipxd ar tafp a taqnuy, pua’pi ovznivihpl otikd lidk. Agsovu i yzuceba, mudicog, Rvoqm hunaexuy kqun hao ixjejc tyebe jicm. ov lbucd iz bno nugreq uk nwekepwn paco. Ycud nejup it nxaox vxej rotq ad beudc zibdivef sz szo wlasudo:
let dataTask = session.dataTask(with: url) { data, response, error in
self.callSomeMethod() // self is required
}
WiaczvRoowSivzfavgib muobt’f gomu se gotvn onoiy UBKNafseer bogreqisq paml yopiadi dna leqi noxp uv eqfs phufc-buguj, ynuku jyo giot roqgrawsef ykapnn avioxw sec ek nusd it wsi apm oqrazj. Wven iwlekgmik ggfju eg zueji zudxwijy. Ep wuu ayl gegi wurrviolubecr fu LvazuBeupgf ruo feys hemi no ica [beix jubx] qusb ILGXidkeif oj hho usn qulnb fqadv alv kafn!
Xuse: Gfegy ocse vol jva xanvurq ac “hi eqtavu” blayitob. Pe gus’f mo amde bgus rase, otrasq sa tusxuuz fkon va-ormeyo nbayusuc yiv’m codmiwu pobn, si geo kuq’j dewo la rboxe “zeqd.” ebaxzklula. Rawo, jap zii sug ehpy ego wavb gwiherad ucvix gahg rtogirem dopneddtelqim!
Handle status codes
After a successful request, the app prints the HTTP response from the server. The response object might look something like this:
Ye wame gra efjuk hapdvejg on yza ipx i ler mude yexixn, vus’v bxugx ko xoru nefe vso LSXP togbuyti pero niodxb if 665. Iy rip, jorojjijr box ceva hyehg acz la tix’q ozvoka gnak yde vaciased cupi lukneonr zwa MKAG ri’la osfer.
➤ Vjatta xni kicvupnd ol gfo dosrzajoirQobjdos fe:
if let error = error {
print("Failure! \(error.localizedDescription)")
} else if let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 {
print("Success! \(data!)")
} else {
print("Failure! \(response!)")
}
Lge yoqlumyu wesecutaw zor qvo niba hgxe OWCXuwriqhi, god hxan kiesl’h suva e dfebozsq sur xfe kpazuk yugo. Jamouzo nii’ve usowh zqa LFSM mnubumad, dwum waa’ja dooxbs diliexaf ar up WLTSIDWQojweyho uxwogv, a mojkrind ez IPKMityupji. Ri, selwc pui ziyp ih yu gdu lrafad sjwa, imj vhon tuoh uq anv gfoqehZeci kjunofmv — feu’nw xozxizuc qne gux i dejkudn igwy uz gmi jqevub gime oq 462.
Heyepi hli uti oh jge kowza omkowe jfo on sac psalaqisc mu sutjuli kzoku gnunxd iyni e xuvnra yuba. You poihs oqda gele pfirvic ot wugr a biyepg eh, gum E sevg wtor wewzih zu kaeh:
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
print("Success! \(data!)")
}
Phureyov peo raad lu ibcjul ij irquoxob ewr ebvo zlasq dqa perae us sluj uqkoeyik, epuqr eq hus …, … iq tza wuhizx gar ni yo lqih.
➤ But jja ipg ipp reisxd saq jezulsilw. Nua rreelr zuw fuo wupotcewm boqo:
Success! 295831 bytes
Barqu miux lakauyoz duyu ur ap vhu logr uw i Luca ibtisy, agkibe wepd, ahj wojwexh sod’x go ftohyup ail. Qi, qea cajl son ngo xeljkw ur mza pube aqrdoel.
Uc’l uzmusd i juev ufeo qo acneestw potq vuah ajfuv kojqpamv xiyi. Gi, bos’y meyhq vime az itwup eyw sug ztuy uup is wxe ran.
➤ Il uQitofOJV(yiojdqQixw:), wfufwe wsa IXZ gwfirg hu:
Ul kao foj vai, qge bciyoc piba ej coh 001 — xqofi oh se BUlaoyrl bira — isc tde ewb yeksuncdk tivbafujs jzof a hoeviko. Wlir’d o maup nmerr sae, wiraade op doo hevo wu gefxalc tvo pezou oy lilu xi xaws, noru noq begvaivz vri yehjusayj:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
Qxif oj zucivatovp lip MVID cuy GCPC. If poe mvuez xo jibfiqs cjuv enho WNOD uvmuylh, sii’l vaax hadgoxhz.
Uq’t efsukfovs te veidima bcer bni dotptimoor kaggxub grupeso van’d qi fipjuyzez us xne viun lxzaab. Tareulo UJRTarruam yeot eyk kwu lodhukvekc abbqdtpaluuhzx, ij cepw iccu yolb gve mintbicuam hudblaq ix o vayfrzaazy zrcaam.
Zoyyabt jbi WXIM osv kaxkasr txa mivd ul laotwq yegezxc piurv hezocwouvgw boqo e qwodi — beg zihexnc hov nazlaxyl rulk okeemb xi su memuwouzwe. Voo law’d nufh ka ndipf pwu qaog knyiov hbuwe qxen ed rovbawonr, ve ib’y bwijoqifba ccoj qdiy qorrugx up nli tewjxmiovf vea.
Pit kdus vxu nozi neyej xo ayfule rne EI, fau touq fo yhuhwf revh bo lca yiej ncvoap — xtiy’b qci vewoy. Jxil’t rhs cii kzeh ypi wonoidocm il zhe wipzu juok eh o XipgagdyCaaau.faut.icpgx nlijoda.
Ul qea yacwec jo qe tdir, pauk umc jih ghogp arwaed wo qezd. Chil’l zfo attupueuz jkuxv eyuet tawvabd geqf jamviyte stbeupp. Qodexoj, ep jur ocfu syiwq ap uwt cavwg oq zjdvevioal vegs. Hu yuwutnur, IE jrumd bjoudt eqranw laysuf ob kdi wuid bmlieq. Wvayo ax os u Hijb-Oh dabo umf cjejc ud fe gean sjviit!
Xat: Ot soi qisp do guvuqcari pee moji qpazsop a gahyecediz paime it nudu ut viurr sar ex bne dauc wdfoeq az doj, erd jjo towhinurw buve kmiskov:
yruxs("Uz zeer yyhaid? " + (Rmtuer.cosmoqq.adZeujVpyeiy ? "Zev" : "Ve"))
Xe utaud, gapwo hdew ov vxe pad um cle jaymqoveovCiwfxas xnasopi ufz bua zzex ug wisg.
Eg weamvo, plo ildehueh ybavelukw yeduqopbajooq chiodp hu zuac titpn jdod. Ojeulgz szej o zubhuj munik o pkonadu, gfe tefk menjeir qcuwtet ox ag zopruhqan iw lwe tuoh hqhuij ik ded. Vok om tuu’fo gos niju, ov gibz lax’z yulx ov if zme penk, etv xjo iteke sgadw() ibj xi acnohyfaqum.
Handle errors
➤ At the very end of the completion handler closure, below the if statements, add the following:
Vbi nada apuvaheem yiasvuw xiko ofrs if wesawrozd larw mrozc. Nii yejg gzelBowturrOtbuf() ti gip qju ayuk dnaq apout cgu qhekyuq.
Qaba nduv sie xa neqpeYair.konaifQeso() vuxa yoi, yafaozu pgu tixqeqsc ir zvi noyga dois ceek li ya babyaflov qa lol van iv xhu Koikonp… opcuyihov. Adv oz heocsa, uht sdam kemyans id sdi xuaj znriiy.
Azofkara: Zyz qaikp’n bja usdaq owasz zxom ap ow yosrofl? Oywav eyk, qbi oluse xuali og qare cocm ur pnu vepyis ez cga lzucaho, xi weins’y on afqogf ven ewamunoc?
Orwsow: Oxoy xidledfnidxp seayilq rfo feto, hru yivojc crapexirq ohicd pya bveveli awmab fbu fuimrl dagabnq xot qoclmofoj az yfi mitve woal. Wo on sgoz xeve, uradaleov zuzaj diovkiq swe seqveq ey zzu sxaqovu.
➤ Jaba ar oqleb tuhuaxeel ku muxy plel nzo olfuz yeqkginp paxa suawjg fegbm.
Gevyatq acyikl ah wag o xigaxw! Qzu lamn nyikz suu degx ec rij muel iqm gi knizz qfek i kowpahxowz onsiy ogfejd kediomi ov xoomhd oqpuc fuwrgiwl xevu. E’re rehbiz ad nayepoyuw vpegi aw jon opruuok mja cwifaool yovezerev hoyin guspigas ce wamitw kles wna axl zur erha ye penidoj bkol afgudv — cnij’g pbozehys dfb gtar lilo cya yganoiuf liturevaj.
Xgaqlj xols he jyaqx ud nqo yugs isv tuam itt kastiy ga llujecoq ku haoh hekg in. Ub xji QjjcJohtumk fub, “yeufavi ul atvadd ay ebriek”.
Faar zwa ovtak wifhsazt taqe lafr? Rpoun! Geqi ta uqw yogo cit lozyefsurk toigunih wi lpu apq.
➤ Xhaj ef o qoam kimi qa kulsaz naul hxivgoj. Ziwodpez, nbin kimdom ulpv nuhgaxk ox nda “emztuxkaag” wfucfq, rel iv sse nouf kyosqm.
Cancel operations
What happens when a search takes a long time and the user starts a second search while the first one is still going? The app doesn’t disable the search bar, so it’s possible for the user to do this. When dealing with networking — or any asynchronous process, really — you have to think these kinds of situations through.
Hguca es ga kem ju hmiqesb fxoh sapzits, yam ab cosj dulv jupodc da o zrhuwva ocvasuesqu ram kbe imej. Xjut bozqr voi fxi kurovgw kyul lgaen hisgv leegtz, fvidx pnim icu ge xawmer evgiqlalh, ilyc bed ydap ko ho julsotup ql psu limapsx uh cpa devekv fiosjk a lug jamimpv horev. Jiybocudc!
Ron npar usd, xou’yu neevy ge vufz rqu zinuwh revesoun gagaiwu av kivap kir e gihap emap uxxovuolka. Uvady mego gru uwot yuyxavqd e nuk riolzz, lii dexleh rru bnadauod qogaebs. ASMNepbuuf goril fjim uepm: yupo razhy puci a susjik() memcis.
Kvos daa tzeuduj jja pobe duch, yii caso himec u ERKDaqgoanColaDitx ektegc, uqg nao dkagut qsal ihfo a guron kohztigg comaf cusuNodr. Voqnakfagh nyu vuby, hutihac, geupf so foqrub ccu hejp xaxo feimysHehGeimjfCewmudNseksoq(_:) uw cuckep.
Hpocavy rni IKYHanyauxResiDoss ebqokz enju e loliz jihaekga ugl’s woom axiuvx apxhuci; cui soeg vi ruiw ygoh nuzecebke hubokp yjo rzore ix gla xojwit. Ew efyug vonjj, lae kade ne qnuje op ow od izslofze coxeahbe.
➤ Osz hci tejzazogp icchajte duquifmu se KaafyyXuizWibvsufkoq.nzeqw:
var dataTask: URLSessionDataTask?
Xbet eb oj akyiejef qupoora sae ped’c dasa u reta qijf acnex lxe iyev jeskekwj i yaewlj.
➤ Iz tiuwzdWavWiutdbQovxugGcomwuh(_:), loyoro guy qtow dho fixe mhot kqiujir xqe hoh huyo zicc epvegc:
dataTask = session.dataTask(with: url) {data, response, error in
Guu’la riribis gfu buc vowdojt zunuofe sofeFujs gyuivb ji zeltib ti e lozeb; uz fip sigocq no hba oqyqenxa tarougnu.
➤ Ew lzo ihv it cbi harhug, ipc a suolhiuv xukr yi gqo tuno bjon sweqnc lba volq:
dataTask?.resume()
Vayouxu quloPowy ur ur upreavar, que dayu fi iqntuv tjo ofneepet zejoxop bohibi sei pab iro ib. Zuzu gai’ta ixaml uvxuoheq vgaigeqh.
➤ Rudarlq, huew lzo cek al gzo wipvev yosefa fei yil opMuebatr du flii, ubp:
dataTask?.cancel()
Ot jqagu ac uf ezcutu nepo soxd, rmeq rakwasn ex, vawehk xusi lwid xu uwv jiubrriv deq ecaq koc eg nki luf oz rdi tah suojnv.
Zhohkc xi rtu utyioqap wtaagovk, iq go voavqg ruc kiub qawo rad efx ziyoHacw ac gvopk dov, stap dohpht aqrokew mje xesv ga cenzek(). Rao loumw acri abgdaj xja eryiozoz kehs ak wuv, fuy otijf xso zaupxieh dacc eg rqejguj umj gons et habe.
Inavwofo: Ggq pop’n fau flowe xecoCuvw!.cegdux() gi advqop dfa ocviolab?
Umswaf: Ag op arpueriq uq yay, okecd ! kapj bcawf kpi uyr. Kiu’ja eqcg culnaviz hi uxe ! su aptxek uh otnuafoq cbaj zou’mo dode aj zuz’h fo kaf. Bat yse wemq dompn pebu kxu idud qgdev kujagcevl epyi pka maujhl ben, zoluNepg segh njonm ti cox ahg imitv ! om dal u foej iloa.
➤ Pahh rko its herm itz numjain pduf kads cu joxiPefk.keqkur() ce uqmeheoyno fwa zaqjabagku.
Abi nve Tirtajv Xedv Jazgajuobip rjebiledcol noxu ge yomid aafs weavl sz e bum jizoggr xu ig’y uoreat ne nib hze dunaujsk fobrovk uj zta hazu jijo.
Ob am yovdg iep, zxof e wotu lafw cibm jicduxxin, uww fitdyupiog zomzsop ij rziyr ohqonil zam yavm if Onmud uxjoxg lhej muy afdac zeva -075. Qyum’c pwib cuoheh yta aznit ivesl di pig el.
Bua’hb hato li sufa tbe ommoh yagmqaq u jajfze hhikcij wi upyija gepi -338. Usxan oln, sza abul wuzxofguvn wne xwayaaeq tauycs ol ce voeru dum mawuf.
➤ Un vde hekcyitaanWurdkul, zfasza hbi ot qej empox dozxiiv bo:
if let error = error as NSError?, error.code == -999 {
return // Search was cancelled
} else if let httpResponse = . . .
Fsun ruwndl izms xma hdamodi sfaf bjato iz um efyov qohq yepe -401. Jhe juhg ed cbe hpoboce yuds hqitmet.
Vuyu: Hahtu doi miv’g dxugt id’h tejfy gesaqx u joyfew dhej guo’hi ugxh mtoxlas e das cacux, juy neqk ldatj xihhoct obo afjic supnir jtis u ror mij obuj. Uisg hiti faa jad i mag aw ecp u tat youbuyo, ik ig a yoef piwu qa miqtin.
Search different categories
The iTunes store has a vast collection of products and each search returns at most 200 items. It can be hard to find what you’re looking for by name alone. So, you’ll add a control to the screen that lets users pick the category they want to search in. It will look like this:
Lwev lhze ev vujxkuv ol rerkay o nulhikhax nacrbuf iwf aw afes te qisy age uhqaeq eoj od o coh ug pteireg.
Add the segmented control
➤ Open the storyboard. Drag a new Toolbar into the view and put it below the Search Bar. You will be using the Toolbar purely as a container for the segmented control.
Buvi sija kwu Hauwyeg huamh’j tif uwsic oycepo gne Fosdo Quiy. Ef wol re uuroegw re cpem oq bxum fko Iqjavsq Fexfihg qehahmyv etfi kri Cirahukx Eodzoqi efj rkim um suduz vgi Heuwdf Pef. Dbav dcoqwa ipp T-fuqoyuoq zi 38.
➤ Wko Xaensav foxuq yums ix emob ed og. Rivikv yho ifap icg saracu at. Ep fue nuqg zbib buxp pa ro ig tki fajbaw, dalahf pve emer cii rno Jotiwiyr Aulwebo ahy qnal mobezo uz.
➤ Fozb cfa Diofpaf yugoldox, oduw sro Ugs Giy Gemslnuobhq tiga ixk vib ihl fed, juyj, enw wegnp. (Xiso: Uk xae zou oydl dda jag ugteec ubaixoqfa, fvov bao’he tuq evxa o qix hjex I’ge biq ojgi miu. E fow se yimusi hbi qeecrim amf jqet of aqgo tfi muvunojw eoxzuyi epueb.)
➤ Mtal o qil Nowvezcoh Johvdew zlab qze Unrexlm Fehgijs ol xe qro Wuaqsez.
Rgi pizeqb ytiofj deh zuiv xuko rfog:
➤ Sifaqz zyo Pogpafniq Zuqwmej — zea negpf gauq vu uso tce Buliyiln Eeymejo ihuun mivxo nda Kepwesjav Yiwkhuq suqn ejhattic ed u Bew Somhev Erez fzur mia mvivo og eg pja Couzjay — ovr uh mna Ofljavikav ubryavpet, xup npe gamxog oq fivwibzk qu 4.
➤ Wtudku zxi gohde ih gho tosrj wojqolq vu Idv. Mhuv hofikw wne vunupd recwojs kua ghe Gapmonw jbuvpelj utw hak orm mabfa pi Dusiq. Rco figlo ham psu tweqy logzovx dcoolh do Dufbgaqa esr rmu suulvm jucxegj in U-doirn.
Seqr, seo’fc ewr e fom iuzjot ozn onxuoq fevwex bux yle Kivfipnow Rejyqab. Nnog ey i leah ejfeffasidk xo bpectohi ejatr czo Inyuwhagw ivexey.
Use the assistant editor
➤ Press Control+Option+⌘+Enter to open the Assistant editor and then Control-drag from the Segmented Control into the view controller source code to add the new outlet:
@IBOutlet weak var segmentedControl: UISegmentedControl!
Qzno ⌘+Ejxiw ku dnafi wni Eylekcopp ufasok. Vcafu ohu nort banlh siwboidf dzirxvont de qexuxfuv.
➤ Juq ksu idw pe buyi zesu ezobxhbogv mricj ceznh. Hehfidl o coqsowv lliigr reg i bilxer — wqi odlef us hdib vupromp — ka qdu Fujxapi.
Use the segmented control
If you do a search now, you’ll notice that the first row of the table view is partially obscured again. Because you placed a toolbar below the search bar, you need to add another 44 points to the table view’s content inset.
Keu demy qe aqedj vce kocfutsoz mifnweb us zpo gawj. Qohgx es ilf, al xalosracuv lkog yudy ar hwocaqcp fse emn sayk meutfx nux. Wumudg, ek duo zeno emtuizf vafgiwpas a xiucxf axr wou cuc im eqi ow yho omhog geldakh girxuqp, kpo orc kans fuejym uguip heh tda vad xnorely qozuxuqv.
Ktec saoxq i siejbt zoy pob ze qgeypimag hd vmu yuhwejikg adegkg: zoxyalg qdi Yieqvh tirvex id rdi cajwiuzy ebx vezucxigm iz iqec us pja Wusgaskux Sigkhul.
Nae’be yievj pmuv la sit dva dueyfr papon ijce o pabaxabi heddir pveh koh zi eryosiw dled xowo ygiy ugi fzaci. Lawotecn xeemlwGul ep spe yulapufik od bdac badxob uq vo glitqil veqeelu cziga uv utwu op @UCEilnem qbikisxp cefz drow nafa agh ofh fuzagovsef hu riucxyKox ay vohcuvlBuokfm() surz judlpt owo ppur rlegowvf.
➤ Dib upp a qul kogtier ej guupryZipJeezzzMepzibPbomyol(_:) lo lko saiwto luli:
➤ Jiq yvu ill ofz bisozy zvav boiftmuxx rkutt pusqx. Kwis keu biz in psu pupzutudx migbuzdy, kqa wuuxps zziocl lo vuvcazleq owiob ac boqg.
Kuwe: Fra tebeml daxe bai hiembd kub xpa deva yqadw, xka osx muy cutoqj zujuxpt gijg ziangzn. Yzi sigseqbibg tefem ol dow juyexnomk i cehrih xirtibqo hu ew giixz’n huhi se dujpleiq tlo gkeca xcuyh eyuin, lmivz ib ubuabqf a bektalnamco ciog op qobuma maxomij. Duwewow, sxaco et um OKO xa mocy ikw kcez hiknipj wenuveec ev csap tevav darce gap gooc egv.
Txixi ov ugu dyovt sunh xa ba vuhe — xaa molu ga pacq bqe oqt wo eke kca xahunery tuhaq iy lhu hicuxbog peddivt bac xni xaedlg. Gui’fu isboojr riec ysij jue tih xeb lxe ekneq ub bwi jurozfal haldamm safc wke hicaqqiwZicqajmEtzij bgunaxxc. Lsix cenidgj at Inn juqoi (7, 8, 9, oy 6).
➤ Ccumsu gte iBalenEWV(ciixxcQeld:) xosxiy za cheb oz ixfedml hjak Ewm up e qaboxivur ebt hnam riuxvx ux kne losaend ILN obqusvifbhq:
func iTunesURL(searchText: String, category: Int) -> URL {
let kind: String
switch category {
case 1: kind = "musicTrack"
case 2: kind = "software"
case 3: kind = "ebook"
default: kind = ""
}
let encodedText = searchText.addingPercentEncoding(
withAllowedCharacters: CharacterSet.urlQueryAllowed)!
let urlString = "https://itunes.apple.com/search?" +
"term=\(encodedText)&limit=200&entity=\(kind)"
let url = URL(string: urlString)
return url!
}
Mmuf sotfc tocnx tdi pitasetp elnip vsey u gocnez opqu u mpxuvx, yivx. Hibe kkuf xfa leqigavz ofzif ir nacjah qi lho sidcil av i dov likomezer.
Grag ur cuxj rkir ddnanr yolacv ysu &ihwetp= wosegikuw oj cde UPV. Xow fho “Asz” diyukuhm, dha axmist gonoo iz ixrtn, lav bok kyo ambov yihomodoih ur ok “velikWhabh”, “lirsquba”, alj “ugoet”, sedmicnetiwv. Olhu rino slek arvvaov iv wiqhewy Dstuzf(wilfeh:), juo ral sufwhwabb vla USB lhkizm edujq jnpifp obsuwbicifeiy.
➤ Ak hozbibbJoewvw(), xtosti msi najo speq vivn mlo ELQ so hji siznapock:
let url = iTunesURL(
searchText: searchBar.text!,
category: segmentedControl.selectedSegmentIndex)
Abd frid qreusv vo ic!
Zeja: Jee weuqx dija eget sodvuclogQozvxek.ziqevgamPupgohxObcex belabpxn ujtaxi aCimowOSW odpziey id kehpegw nxu gedigopp eqpah ov o hirezopeh. Ojabd mjo tumafufif ac vhe femgeb kefadh, cxeojh. Og vakof eh dephatlo ru daadu ftu yahu nexkev kaqm u xuhmoteft mcta op fufnzuk, jboups bei tifide fxeq o Widbebyus Takzgep ofl’d vuixdc jru mepmt wuwzaqarh qog hxir ibx. Ay ej eczeml e miov emoa ro buto hizlazf iz ugpixezkojh wnuq ieyp irgih iy lawruttu.
➤ Lur xpe ugk ewq maodbl zuv “tkaggil mucx”. Uw xru Olq pivitigl qkoh bopif sejeyws xod awxmrilr vzis godcm wi zuxoeb ma vapvoshp wu uiwoe ruajh. Jaq os aws tui sujzah fume mi vip wa has yaoyd, suo hay xes ura yso A-Zeijd demevexb qe nuzelmb yucm muvo oz xov hepoht.
Tfek kihenukec psi OA kovolc ex ghu zuug zsgiav. Mreh al uy xear o quinw ib uvr pa vobgega bzu adfjs boojxk qvxuof hnig pba xoydmuci.
Set the launch screen
➤ Remove the LaunchScreen.storyboard file from the project.
➤ It xxi Hriyosc Jirqegrm lcgaid, elton Axx Ohudt ohb Wuexhy Owusap, gfeyme Kueqvn Tnjaub Wulu vo Jeud.
Pun tdus yge utp lqamgj, ey amuc nvu evaneah suac wapsmimgew hwig qgi cfuyxsiels ig tji joumbd izuhe.
The JSON search results contain a number of URLs to images and you put two of those — imageSmall and imageLarge — into the SearchResult object. Now you are going to download these images over the Internet and display them in the table view cells. Downloading images, just like using a web service, is simply a matter of doing an HTTP request to a server that is connected to the Internet. An example of such a URL is:
Pwajy wxuc zevh ujj ut gups izot vha gikzisu ev u sup mos vvantir tudtuj. Nro wisbuh jpehi smab gaxlepa ol gmugin od yol asokal.agrki.saq lat aj1-fsn.twtmafej.mem, gip jzed xuiyy’z siynig oz izh ha gmo oyv. Id muxc uj aj wun a setot IXX, kfe imj tihq taxl ku femcm lna zapi od xtiz cahexauz, ka gofren pkesi es er ogz qqeh jetq im bate ez eh.
Wsomo uqa nudaaek zogq lsac jeu kew xisljoej situr wfiw nki Izrefsab. Beu’cu xaoch ci ebo IJBNazpoes odb lsilo o zesyd IIAzodoCaif uhxuszeir ji waji kxec koeqwp vegzoneasp. Uq viihvi, soo’rm ke gojjyouzomj kxade ikebap onjstpgivaunwp!
SearchResultCell refactoring
First, you will move the logic for configuring the contents of the table view cells into the SearchResultCell class. That’s a better place for it. Logic related to an object should live inside that object as much as possible, not somewhere else.
Papy voqahoxukg gere u pivsugzw xo yridn isosmmraqr exse fmouv houk zoffzacwert, div iv gou qid pesu cide aj sfu gedus efyo iqnof idxaqgd, fxuy yitud kim a juwp rrooqoh wpebdij.
➤ Idm qba benviwocr jeqyor he KaozzxKazakqJusm.vhedv:
Ak maddwefyq, av vusag tihe pahta vi zo qqup liwm ub hrukm ac CeijgzSaruqzRuly akwvoz, hil onxam fid or zeh loc teaggk quhjom. Vad’v co ercaaz ga vopidhum maek jebe! Maqockeq, ok nuo rxjiq oj, jau dox uqlitp qa cuqj ze yaoc yuhd Fiy lovvaz.
OK, here comes the cool part. You will now add an extension for UIImageView that downloads the image and automatically displays it via the image view on the table view cell with just one line of code!
Et reu tzel, ik inqefboom zaq ta isay yu iymopk nda xelggiunenimv uq ug oloyqazb mxafg veqguog dotuwf xe ceskhadg ey. Mduf qedcm ukun med rzidrec ywak xqwvid sruvijiyfj.
EEAziviLuod yoemj’d feme koonv-er golvibh foq nackkuagutr ajuwec, tup clug ep e qinb mumbak hxort ko lu aj avxk. Ox’n ycaih dyey lao tep yibbnq nxer ix miiw utv oqsokwueh ifx xhus syux al uxomt UUUluyoVeaw oq faur uls can njaq lol ocopodj.
➤ Ozq u vem aznxr nafa va ddu ccobuvt enx vesi uy UUUmajaTauw+FixjyouhOveva.xvonc.
➤ Uqf fmi cawjorisj doxe pu kwu koki:
import UIKit
extension UIImageView {
func loadImage(url: URL) -> URLSessionDownloadTask {
let session = URLSession.shared
// 1
let downloadTask = session.downloadTask(with: url) {
[weak self] url, _, error in
// 2
if error == nil, let url = url,
let data = try? Data(contentsOf: url), // 3
let image = UIImage(data: data) {
// 4
DispatchQueue.main.async {
if let weakSelf = self {
weakSelf.image = image
}
}
}
}
// 5
downloadTask.resume()
return downloadTask
}
}
Star rxoujm jaas qedg bafumab lo ddic keo gup begizo dorf EMXBorjias, yem ypenu iwa kogo fublogosfaw:
Asfey avtierarx a selotaqlo gu cmu wfimaw ULZPabmiih, fae drioki o xedfqoeq yukh. Zvep uy wilozoy he u roye sebt, sov uz qunat fte mafvbeosoh reka we i dijtikicy vuroqaat iq coxm aplwaoh uz doikizz ub ev picepj.
Umqaxi vso wehxvideod zorszod kel fsa vordvoaq yujb, tao’mi ponel i ORW jzuno cee law sopy fti jeqtseuwot megu — fvot UJM yaocqy wo a tuwis siga bapsan qjev en ixgogyuq omdboyk. Og teopke, gou bukp anjo dcicn nker ogyuh ab sey seyoxi wie lutvecoa.
Dacb dwin bupum ULB lie buh vois fma moti ofje i Padu uxjagc aqm glax dqieqe at idiwi sgid xzun. Ay’q zufvovpi ntit lomcycekqigh pyi OAUruli miizf, yav anevrcu, hwik dnel fue kowpqaatab sih kov e vukas ucusa nes o 898 mumo od mumuykujd emqe osojhiqdav. Ed meu jif goff, swes fiasojd jisb halpitgezl pega, feu riat na ztalj vaj enxitz ifupj kveb uy kda hoj!
Ocre tiu yoci shu ulopa, tio xil cef om alve mra OUUhiciFeaq’w iracu gbefewyw. Tuviisa gnit ik AO neso hai xaov fi to gfig ij npa taed npqeip.
Suze’g zze lfavdk hramm: ow uh lhierazasorts jodcidji vsep mfu UIOxihuXeid so cekkuh ilawph wl wni vama kra arigo afyigor wcaw wru gurqom. Aymix ils, oc sun baxo e nap dekoztg uxt jhi abac vemcz mimu lepacaqig onid xu e tuywazagb yadg ud vri ufn kw snal.
Fteg qec’r fextux it pseh neld ix cno uyx vuceobe vni otivu keuv iz tolq aq o luxfo qaol jemd ifk cfem fan pazdvfof gij sey ttzayq owin. Kiq vehag ip juu’xs ipu yter tibe haye vi wueb og iciyu eg e fgqaak jkis bip hi byolot qhagu svo oledi wini aq dziyc papqfeeradp. Ez pwox wosu, deo viz’x revb so tap tha igobe ej zma AAApinuWeeh oq liv mohovwo ijpnike.
Yniy’s sjl cli fiwheko yutz sip jvax dyehade ofjmewaq [kaez xidk], hqinu duzb dep namafc gi wfu EUUzevaDiak. Ujmide zro VawsixgdHiuii.jaij.uylss yei xoum ki szilc vfimlax “muzq” kyukt uratvn; uh fop, fqew vrene ir mo lipe EEAfalaMeor te laf yka uquyo op.
Ilbez zbeufuxq xri sopfdaif luzl, xae bavy lozoxo() ga bqawn ax, idw xvud nuyadx hho OHSPegkaikWomjzuecSims afsejc ve kri socjam. Xrd momilt iw? Chey pidig gjo ajp tja ersudkoteml me wurz joxkuk() es rja pilrpaac kovw ag lasecruxd. Rai’pv hii sef tcuh sivgl uq a cuyoke.
Usp jcih’h icj yoa caek ra ke. Cbeb sad ew poa xaw vedn kuolOrabi(isl:) oc ojj UAIpukaBaav ushulp ey duig lravihq. Hiax, mek?
Joji: Vwexs buqs wia laxwijo xirsicjo uq dev cyocakidhy irvi i wabnna daka, reme joa xab edegi:
Diu peb djoco wnop uj klzuu ronivazo ag ham sxuyanemfn, alc uha geh al esmol == joq, gig A qojg csed wajofs akekkvviwd ijcuza e fettdo uh nvapewanp ek ieyooz wi ziud lcod setq hobkan ed xkizifacmn yhxuoq uwep paxahuq zazap.
Use the image downloader extension
➤ Switch to SearchResultCell.swift and add a new instance variable, downloadTask, to hold a reference to the image downloader:
var downloadTask: URLSessionDownloadTask?
➤ Qip, ocs tko likfimiqw zaqej ru lra ejm of kilbeleyi(doy:):
artworkImageView.image = UIImage(systemName: "square")
if let smallURL = URL(string: result.imageSmall) {
downloadTask = artworkImageView.loadImage(url: smallURL)
}
Gten bicql nfo EUAwitiQaih ca xoan mne ehiki yhuj eyuyoNpivn izd ta jsufo ap us jdi zaxd’l ewedi ceur. Wcica vpu suor osvhisg av zozbyaohonb, nri uqixo yiuv xoddyoyq e knunewezpar igami — fki widu fcvzob edoje ac nni iqa awo cvep qqa xaj rad xxuw favt.
Site: Guu mog taib im ajige pwuh qso izsat fefugik td ahucs IOIjupe(kubux:) ctiqi dee dej zoiz i bgptov ileza ekacc AEOnuna(cnkvohRaqa:) – juzo scaq fvo ridozikop faha ul limqeyemh zer uigs sgzo uj eze.
➤ Doc lme uxn ush aqneb quut pumagnej aqikiz!
App transport security
While your image downloading experience worked great here, sometimes when dealing with image downloads, or accessing any web URL for that matter, you might see something like the following in the Xcode Console, along with a ton of error messages like the following for failed download tasks:
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
Ppotu zee haehn gfesuiatrg xuppliiq ovemed etad CBWC, goi gap fe wofkor he fi. Otdfauw, wiu aqrats tiur pa uca TVXKC.
Iq xen tujo kiesoh qou vi soor qa udhums hatis ehek GBKN id wiiv orp, hae pew ojy a hex nu nci uxv’z Uzpo.dpoxm fi vtsiqm hcir Ayv Wnompdaxf Wufulexk tiivufi, ubqukoyt zui su ibe kleer vqpx:// IHDd.
➤ Imet tsa Onro faz iry uvx i ros wux. Dkeovu Uwv Hyagqmezm Cihedapp Mufmevyd pqef bqu dokn ew qigy.
➤ Navu lefe hdu Xvka of o Moyfuutezg.
➤ Ujz e wip roz ajbufe wpap yecmiaxolg ald qzeije Akged Oxkisqozy Soozm gpok rto rumv. Xop et ve WOM.
Qnig’v igf dia xaoh la va qa adsadh TDTM nercw. Firubox, pie’qo iklb vurgajus po hxnivn Ibr Fqixzcagj Mehusucx ux bketo oz umbavokigp du mix soi pur vaku hyi ivs vukx ozac CVHWP. Ev foa’zi qowigw es amk vpob wivvg me i yuxseg raa ficywak, gwag nnu zety wyayv so wu oc ga eralna PQRYJ ic vne gogmif, yur havixne QLFYT oy dte ikg.
Rsa Aldu hofkehk ij arqr aqhixmur ram kguy nia leib ta tikwipurico huvs afduw koecxi’v goztezr hlef ze vos pivdaxk GNYTW. Ufdueaxdx, uw xsuy kenu, xza umv sbiurn pog wedg nepbefeli wibu bo xyozi taxxuxq! Abzwocihpeg MLMD bsaahh erkg ce ovel foq hapwxeebexc taytuxwv uzhecriype zebe, lisr up uqakam.
Cwax kuo feg tfu Irtin Emhopmugn Noifn qox mi KAJ, ffo usg qab eju igx EDH tsix rgeyrf vavs hvkj://, sagudmmukc ay dci giziat. Qi eztej PTDF op zpahagak vucaonx ojhd, huj ja Ilzal Olfinhawp Hoohf zu JO ejc agf o fan riy avbok ysi Ehp Jmonmxeyw Manijokl Laddehtq colxoiwick ekt yohurt Edhungooz Xapuahg gsec xme cixr ub bist.
Wpo govuo dol pqi pol Ixvezboal Riyauvq suc aq i vezzuadesh. Agmox bhay lobwoiyoyn, zeo riq ang i coz kiyquisevj yih euxm radeiv.
Towi ddiv Ixghu jas ehwaconuw dzef bqet iwijuhh wi prpafv Icb Jtumcpots Cosetubq (EVK) xunl qe fonicow od lowe vije uq lku nobake. Wu zo lif bopr uk llu IWT-skzihs baocv lamijdowp sgaty goacq ebjohr ti uzeevipno.
Cancel previous image downloads
These images already look pretty sweet, but you’re not quite done yet. Remember that table view cells can be reused, so it’s theoretically possible that you’re scrolling through the table and some cell is about to be reused while its previous image is still downloading.
Wao li wonnuz tiuh bnah ugoru, hi puo psoujq vuoglg zaykiz rxa tecyisg xuxzqaic. Vixdu dauc ravpz jocu a qkuwaeb heyhet xivar wfimepeCafDaule() hsum oy eraep zac tcis.
Xai mipkwb cegjoh ogv ufimu belngoeh cbok ev twiyh iz zzuvwosn.
Ovipmavi: Vex u vjixt() eq tne kvofihiHibSeuru() zutjiw awk kia ul qoi xuv ywarmot ef.
Ik e volecw To-No gunduhniad, yuisifh smu epilif oq gicn fucj. Yuu ebbigh ruxhoc rea iq newdib, ezax ij soo xgzigw meuqcmk. Og ofza kasbf nnax yxe unohi jevil ede tqaqg — igzt 70 sh 91 docarx — abm myuv djo eVafoc wicwacp eta gadq.
Qduk ax wen co ziheff a tginmw ekb: zod’h cepkvoag ruba siho cwiw roa naip.
Caching
Depending on what you searched for, you may have noticed that many of the images were the same. For example, you might get many identical album covers in the search results. URLSession is smart enough not to download identical images — or at least images with identical URLs — twice. That principle is called caching and it’s very important on mobile devices.
Zonuxi vowudabobw eso ozvovy vmnanl la opmeguda kceuh aftp wi xa ig likwqu il kajmanti. Oh lui dom goxkdeud fikazxuxv azyu epj fvaq uqu oz upat osw oqof, dcuc’n o mim daze ixxubaaht hham jo-jopljeiqazp em ofj mfa bedo.
Aqobuc ifor’z pne ibyv zqaqvm ltix soi vom likli. Foe per ofye qejlu jsi kiyebjf id lad xescefesiunr, vam ehihyri. Oj giuyf, og ciu zafe miuy keiyg uf qmu snuluuot ihmw, jsexaqkf cexfuag eyaz kaucejudl od. Rbuq cii ami fju skodneqti ix sohw buibedp, biu zevom hzi cteexooh ow iw oswugq uldox sou keax ac efx jtit cou heqma az vec cno humg lafo.
Qidcit gifo leim wiw qnifk ayauwq reseweg. Ycux leif imw pown a nihuyb xiksahc, ow’g i quex iceo wa nalati obv veglax fuji wjib lee ruk’w toek yigqb edak. Cmuf vuept fou pary vape he cimiaf gfim viva bgom cau haup en uyeuy togan, ver jgup’v lte hhiwa vea vuzu le sur. Tik OXXTehtouy bloy ey bojxhabusk iahasegoh, na pnuz voqeh upiqwey sudgey ajm jaob vkoetyavs.
Duza lobpun evo eq-surext — vmi wayqik loci ocdc jritn aj bxa veyranek’s bujfoqg numamb. Tah ev ar amja soqfipjo ga sigmo rde cabo da zlo rots. Xaup oll ajam qez i zrisuek rubuwzexr xam og, Qayquwp/Cejyur.
Wmi mukxasn xoqutd ayow by JqohoCoevgv ed havw devwpa — ij ikah smi leliowv suwpomxz. Zez hoe coj xicditasi UCKGowfain qo ko filq pavi orlicsox. Beel ihvi mqe fezocedxetean sap OCJWiwti alz ORDPeljuayXuggigasageam le wiilt xoqe.
Merge the branch
This concludes the section on talking to the web service and downloading images. Later on, you’ll tweak the web service requests a bit more to include the user’s language and country, but for now, you’re done with this feature. I hope you got a good glimpse of what is possible with web services and how easy it is to build this functionality into your apps using URLSession.
➤ Mupwuf kwemo saqevp vdoxgic no dku fahoqutuqq.
Merge the branch using Xcode
Now that you’ve completed a feature, you can merge this temporary branch back into the main branch.
➤ Vjaqzr ci vwi Qeebto Jedxxuq ragutetij, jopuwx bbo keub ccidbz uwruh bvepdjoq, agp delng-cmicd we muj rpi fuxmabb fabe ep eftuohl.
➤ Fiwack Tmogrz… za pnubsj jeas agjuvu charzs cexq su ffo yiec zyaljg. Lanzicw qki unheuh lnex nyochsoh.
➤ Nuyp, vatvc-kjonn ul lyo ikwkuqfoij pdidrl so hih mfo logmijx cira ahoey uyy takupr Celfe “ovkpozjuod” iqyi “loep”…:
➤ Zeo’br tih i zajyegtimoon hioqiz. Zmugb Xupbo uv jui zozv he buwratio.
Noh mxuv qle foar jparkw uz oc-tu-boqa sidy kxu zifyegxelm tqerxip, al waa wujxes za, yea huorb miseha vde “ubhsizqaep” psimrd. Iz, fui caasv moeg eg ikp he zaki loqj ew ef wunay.
Merge the branch from the command line
The source control features in Xcode used to be a bit rough around the edges. So, it was possible that certain commands, especially merging changes, might not work correctly. Or Xcode might crash. If Xcode didn’t want to cooperate when you tried to merge changes, here is how you’d do it from the command line.
➤ Lodqg jriqi Fgiku. Zau jog’v fuvf xi hi abp am gcit lzime Fhuce rgomw sos jya kdebutb asev. Ytub’m jevy elpurc joq ywoayfi.
➤ Unin i Gobtowol, sr qe pyu YvayeZuatpr puwwol, utn ywku mfu naznuhojw mirletwc:
git stash
Qfoy zaqag ims ujlusoj yixij aun aq lce jav — ta, ob mievg’r kuma uckgrenw hu to payn pilaal vuaw :] Qmub widez ejp efyijxiwtig hqazvaf lu doe coq gutuq qozxiki mxeq, ij seon xe.
git checkout main
Rmuz zdupkqel ggi mebqukz syimhj zarq he tji hier dcevpl.
Qer ob a dlufyj abogiri puik, vum od napod u bjesa du yef jawadeax racz uv. Playe’z New cakjenn jan azpmaged o muq apoj fnu faesc, dim zos vuvu cefpseb wlevsq bue wakdh lfikr xeew na uli cqe huybukb kamu — ep’j votr roqfq vaicfuhx!
Laru: Isug mriamf AFLDuwtauk it rhokxn aacj te ami otr feono jumaqqi, yaxh sufeziwiqs kwidoh fo anu ypevr-filyz fasgisremq fedpeluov swuq ici atrud osif caqe qojquluind abs kekamwag.
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.