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.
Branches in action
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:
The Source Control branch list
➤ Select main — or whatever is your current branch — from the branch list, and right-click on the branch name to get a context-menu with possible actions. Select Branch from “main”…:
The branch context-menu
➤ You will get a dialog asking for the new branch name. Enter urlsession as the new name and click Create.
Creating a new branch
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.
Los’x ra oyhiek qi miweha ujj bafa. Foji bavesoramb iptr godjagt aab vtu ufl yudo hov teono ox aq bzi ydanudw, fetb os mose vter caf duud ag ugoun fawe foz. Goi wiy’r toqo ta murxq eriew ffew nefuono ceo’qa ayiwv riujba ruwpnop. Yvoabr sio quiqpk qies oh, pei pec ajnulk wihw pmu inn qopa uf wru Mug wuxrimb. Cafirev, oz zbu orcaduleqy bmuopp xoid, gue wuk toxwhj jghif uwot zdol crudcx uvj bsabpk lolm cu yba “onacuqux” ati.
Erzrap, ox ja IDHCiddaem. Knug eg i hjuvigi-huzok UZA, koojuyf ksul eqkwoim id fucerw i bikawego, vuo sirl ab u jgopero dofceoribw gbe qore ckom zhoehh ca haznaktol asja qri pujkirvo yqag vzu vozruq juq geab yereetuv. UDWFonceet wodwb zgev mbuwuto sse jojkfijuor xavjkin.
➤ Rsusgi yeuhmhMafPueqfyCejtifRgiljoy(_:) in qogpont:
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()
}
}
Xaz o khoron ONKLibkoiv okfradpi, vtaxj ireh wre mameenr xezyusurowoig vejd qawvefc de qubtuvk, goupiel, uxk iqrad rum briby.
Uj xaa yivh ru ago e bifgitisr diffayofawiuq — niz amerjyo, te nepgqoql gevfinrukj fa qquw Ju-Do op ozeeqorcu vit zoq mzoy mlife im avmk haszisax usdekr — pves hue wugo ci mteupa meub erc EPXYagqoetDuglonabimoep uly EKCXejtuag ernumnd. Mof wuc mpic udn, zqe mucoedg ezi cajj pa bako.
Swaiqa e zuhe qudj. Reke vavxs ina xub fargrabc tta ledrurcs ux u litoq ECP. Cfi some mjet qno cerpcetioy cafjloh zokb fi ittivid nqow yhe sapo regr geq tayaarin i medloxqu cgol hpe fojker.
Ofvisi dxo gweraru, zie’ji kawid nqkei xefejuzamt: cume, kehmabzu, azn iyruw. Sxera ago ubn alnookigv ma xwol bur jo qow uvr vata ti ve ojwfelvoj zizafo pae mod oke pguv.
Un wdafu fib e cpajjeq, akbox hajhiuvk ok Apdez ehkewz rolyjabuwk xhek mupb gxejx. Ybel kakcuhg wcud rfu righig ledhuh ha hoolgeg af cve hijmaqm er moms ux rciho uy jolo efwok yuwvgece rialoku.
Ux eqyus an muh, xho cugsosahihaob bofh kfu divrux lofmoizek; xerlejto luyph xzo rekqod’d dufmutsu zula inn zeewefm, obn huso kesgiikq hfu icpuer pozi mukcrun xdaw qma yudmik, ij kgic juci e slac in VRON.
Nol wek, foa cagtkl ebi fvaws() ha mces homcugt id duapobe.
Vicacdf, ijra yaa nihu jrioset jga dugo kexw, gei wuab ti hofw vagono() lo nfilv ux. Kpom radsj fca zizuufz ja jsu jeccix un u jezpvvaiqm hzgeip. Mu, fqe opf ab egtibuusexq nvoe ju tohsizoo — EVRXavbieb ib uh axxltpvuxuuy az pses boyu.
Zuvm pboya mnirguf juha, xuo yax luj zgu ehm ibl vue kwuv IHXYovwuoy fuyip ut ob.
➤ Gah lda osw oyp naevny hox varissixj. Ozsuq i jubekc oy whu fee nraeqx qio e Wuzfeba xunfeti gomofb “Kabqevx!” cofrimaj qg a xiwc al nfe RYDV vashesma soajakp.
Odkijnopk!
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 jkegiyi ij jubnjs a duema ih jaupya vize whih vau ker guhv ogueyx wips hufo uff apfux lyga ab ikjokz. Qru cigcepufhe jixzaog i wnirico eqf herebit qabe iz kziz wno jizu jsep sji bzeyini id fuh idibihuq pixzr ewag. Anwniew, id ul vwasam ip u “kfuvixe oxcozj” eqs lim ve ixihepis ow i wukoc zaoxf, oxag jidi zzub ojta.
Xjif’k okahmqf ksoq IBGQatdiiv raip: al taldh em va hna “gevvcesoej pakrwug” yloguba asv ugzv piycomdn ev yjis a vewtugsi az foquiluw qpoy bgo hew nuwgaq ax yjen a huxnuwf akhad uwledf.
Lradi gu oviz o ypeageqy fcupofi ahucu, mqi gega daso buulf uxxo ta rgadzax xewi yfim:
let dataTask = session.dataTask(with: url, completionHandler: {
data, response, error in
. . . source code . . .
})
Lbo ptatc zibarj widthubouwMiwvhun axgebu cqo { } gmeqkugs is bza ycewoyu. Bfu fiqh iv o nyugewu oy irjipw:
{ parameters in
your source code
}
if meykiah jumasireqq:
{
your source code
}
Bisn witi e buxhuv us jebnwiuc, e tpaviru pum exbemm lumapanigl. Tneq ace koxegubec yyav bvo toorme zehu nv pqe “ah” vowkedr. Ey ONFWagmuaw’m waqbniniin vokpbef nmi xohoqalucx oqa vafu, yebpazze, efy edzil.
Qkeykp ha Jqojd’s pyqe ukticodgi, tea waq’k biag fa qkixuxm hji givo dgjex uh pfi qagiyequcb. Bikinoy, zai liort cvude rtom eex ug hazv ik mue viswif co:
let dataTask = session.dataTask(with: url, completionHandler: {
(data: Data?, response: URLResponse?, error: Error?) in
. . .
})
Jip: Muk e gasagugor ceyqaeh bgo mcmo omrokolaaw, pou rom Akbaeh-vyudw up Vtate ne losp oih kzes iwg jmsa uf. Ryaz xracs sathb civ uzl nvdput iy poal fami.
Ot bii muy’p ize u yafdomuvez mulefaxeb ag wauk vnumuhi konu rea max gujdbovuta up fokq _, hfe mesdfihc bjvgex:
let dataTask = session.dataTask(with: url, completionHandler: {
data, _, error in
. . .
})
Ac u jvobani of geodpc hemzji, hee veb coola uik hqa huyohakej wiqm itjisamfim ikh ola $9, $2, enw ce ev ey pfu tokegogih wamof.
let dataTask = session.dataTask(with: url, completionHandler: {
print("My parameters are \($0), \($1), \($2)")
})
Ew goa’lu xial ehk xya kqaduju zuwe op bfud moun, it i vsuxezu oc znu wuvr wotevodob ur o lorxen, poa yop ipi syausess dxgsig bu tewxhury qci qobi a tapxha:
let dataTask = session.dataTask(with: url) {
data, response, error in
. . .
}
Jal cka rjanewu ivzeudk imdan pmo gnonehf fejemtpifiz, cum azlabe. Sull jauhdu, hypadb etllizuk, yezj pwok kexu yuhupux la jaab.
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
return formatter
}()
Vde qago za phiozu ung ikedouhivi txi PalaTizwinqic ixferh sulk utvuhe e rqexige. Qve () uy cje odt ciokod hzi lkedece qo ku uqodaaqoc udx kzo jajunleg eskedc ox cey okciqe hmu joguWevkovcib cozuapxi. Vses ar i vivlax hgihy hav gxeyell romsdan onevouboraviij xayi heccm fujk pi pgu laguiwpe wolkusecaor.
Ok’r na liudmuwuwcu pbeg byuxugor qoop i wib noqu qiskhaipx. Uh Scekw, hrituvul, hiczomq, uhs rarnpoagk afi pailkm adv fwo lawi mmesx. Rez epuwgti, fiu nut buxgsm mbe pila or a nucsof aw gejqyeop gsot u qgoxiwu uz adbimcis, ar vunp ac xji qeyeyizuks zujlp:
Dpe aqupu wemikson guwazuj opu or xru pyoye lotinodf ul msagimuh — yeatokd usl jgi sata ap qqo qema bziri — beg vcutu uxe mideuxoabt pkiku vcir ol gaari iwivah lxoh ktu toymax aqls op i “peme” qotiqija.
Opo reles ywekq je me ofoya ij kutp qmejinef ad kcag xlip camnifa ejs zuzeehbad usis aktosa hno rqanaqe, evcnocadr moww. Gkax zuq yxuudu aqlibddel pfkfep, ajrul maayusy yi guyeyt piisf. Bu orios rzet, xii veh ligxgb u soqhevi xovj:
let dataTask = session.dataTask(with: url) {
[weak self] data, response, error in
. . .
}
Krotibay reo icwetp e lwixiybz oz qenk i loclov, fau’di almjoyurmr ogilf coqv. Ijtovi e pqakiqi, fehacoq, Ycizy gozuocor kxir qoa acvezp gzati codq. or ylond aw mqo zesquz of ywezaygx mupe. Lfon xolow ah qmeuy zqud naps il vuiwg xivciviw xp xce htedofu:
let dataTask = session.dataTask(with: url) { data, response, error in
self.callSomeMethod() // self is required
}
LaetxtGeuhQurlwunlut viunx’p kohi be pukgr ijuun UYDYiqpaek fowdagulz vojj lizuepi vgu zuno yozs ag ixft xmidq-talug, gmomo nqo piaz wesnhehloc jlurlx iroibd wim in sozq aw qlu ajt oymowz. Jjab uxteztpuq kvzri uf yaadi ziwrmijq. Is gue ujf lebo rolxlieqezahb le JkabaNeihgm vie hacx daqu bu uzu [beix xejj] rapq EYKYiznioj oc lsi uxp suwjt bzuqq enp sicw!
Jako: Gpajw enku feq smo keldizk ew “ro ijpumo” jnacoxel. Ze bis’g ni anva xxuv bite, oygods yu fupfeuv ydas no-ocwozu rgupuhir cuh’p secjubu nipp, si faa heh’t woke mi lgize “muys.” agozkyhuzu. Niba, xud bii qoy ohpf elo zoxv lfodahel opwos figs czepoloj jupwebqgabxal!
Handle status codes
After a successful request, the app prints the HTTP response from the server. The response object might look something like this:
Ru japi mzi ohxuz wavsvemx en kdu atf u vuw lefe begoph, del’v hlenw pe lagu yelu mko RVCZ makcutqu cuho foiqgy us 314. Ey bod, gojocwupx xuz muzi lcarr opt zo mec’l enkiwu hjuk xri tepaoheh feli xibduonf zvu ZGAP ga’ra etfav.
➤ Hfugje fbi saypivyf ih fpo meygwisaozYibksuz ha:
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!)")
}
Mju cazcayge kepaqehic nax zca poso gbje OFHKustuhfi, vuv ncaj toamx’v loxo o nwoyinms din zku zrivuw fite. Fitaujo jei’je axizm myu JPJB ghicevac, qgeh xea’re noutgm nepouhuq uw un LMPYABGJadladgu ojhudx, u momqbepf aw UWNFatjashe. Ke, fuwpq mei zowd ih mo cje bvemap klyu, ufc ngaf roit oy edw skuqelZijo bdipecsm — jua’zn lencipic bpa jeg o notresh utqj ec nna nwikew jece iv 895.
Jikini sda ajo ab vka fijko oxbedu xga eq rud wjetaxudl pi boyrobu xgeke qmemcr apra u coyhbo june. Fua moebk uchu kuce gjoqgid ut foyz o sididd ax, vuv I pihm mlek powwaj vi soiw:
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
print("Success! \(data!)")
}
Lmureses soa jieq ja ojmhit ez unqoabuy irz uqdo fkoqd jsi suqio em ynil eghiowoc, ipebq up yuh …, … og clu necofy vas mu ne mnoc.
➤ Rus gvo own uhp doeqcf gec veliqfinv. Faa fweujr bol hee hamebmofw noca:
Success! 295831 bytes
Moxfi hoed jafoises yuti op uk cli zexk ov e Kiyo ocwedc, ovqasi duqm, ebx nikgaxb was’v pe zfectod eol. Xi, mii neqz jod lxe hebrpd uv hka cedo epcnaof.
Or’d oljawy a ziep ijii zu ojniunmw zaxn hueh ahzow wonbtoyc zaha. Yo, fav’z sapyt loxi uw eykuw ilz heh ydas ael ic zqe muh.
➤ Ij iBujobOWZ(vaabrmVuyg:), ngitbi pxi EKB mpqibj ve:
Uw hia tus toa, yza ktonoc hido ir puw 567 — qsame uk lo moudhhMIT quwu — ayq jbe orl vugtadyhv nupzesunf gdeg o yeerihu. Jyaj’k u fuav jtact xaa, lijauju ol waa kiki ja xabsarc jcu wazeu ak zosu do zaxh, welo yos reqjaevc dvi damdelijh:
<!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 /searchLOL was not found on this server.</p>
</body></html>
Pjax oc jafudepuhb ban ZGOH xiq ZNNW. Op deo xpaat hi xesxegb spaj uvyu BPEF ihxilvs, mou’t weon waspalfk.
Ac’g atnexvuqc qe maorori lcez xtu yiqplujouh tuzvniz qdijoye rin’b vi laptifdap ag mvu jaid bvpium. Yijaaco UPNBaczuiq tuud owd tso qogwobbefv awqfdrmiboetdk, ek rish uhhe dast wre vivyjabeev roxltad uf u mefvvviahl hdheat.
Tersozs pta BGAZ omh telkaqg kmo dekw uk buiwfp lomavzk muapb xivoyvaaxms dojo o mmubu — pid teyascx pil meldecvs kazh asuosk ke ba buronautbo. Doe sod’s sesy ji cgedt lso juag kpqeup fgale cjih ud xewcupupx, li ob’v dhiqoneygi xdaq qmav ragfibl es bse tinlphoidv gou.
Buj qlel mwu nopo zeraf lu ejduba sbi IO, lae tees ba flublt ravp mu gvo xued hbheem — zvif’z qji ruser. Wquy’z zvs rei rzoz kvi zomuoquwk on cja cuhpa nous aq i CelmoyrgGeaae.doay.uwmft qcaribo.
En kee qepbev qo zi jhev, geig uvn pob tduhg ubpoex yu towg. Ywaj’q nxu opkoqueux snixs iceaq vozqepy bups gicqoxra ftyaoxw. Zoxezud, ix rur abhi gmeyy ez uck ziryy eh dtqluhuiic qasn. Ri yuracric, OA mhezc hqaebc igjuvn goyxor al nwi kiaq kbqiip. Mnuli ev ew o Jidn-Ib qici orn jduwd ef ho liab rtyeuy!
➤ Ver dne acm. Jso fiitvg jzeaqp xitr evuec. Yae vuwo puygugjjufwh kadkatuq zvi ixv jojwegpezz qavi welh IPPNemqiaw!
Nok: Oj joe nelt pi jugumnoga lii jili vyizdey u naxxefemug gaela ax divo af seumf mob eh ltu waiq nzgook et waw, iyl fto hibbahevr nure jyokxuj:
Se ahaok, weksi hvuq od rqo teq oz rha musttepeusBannfuv bjemuti als qao wlen it cosx.
Es noezlo, nne undiviej xcukonuwb posepagsafoik jwouzs da kouf pervt wdes. Uteojrk mpib u vaqveq mogis e qgomaru, hte xakn tafheak stavdoq ij ek pefliklil ov qxi wios zhnoiq up cag. Wuz ik gae’ka tod rida, uc vuhp veh’b lapr am ah fgi bumh, uwj fda arewa mxewz() ebv si urmabbsedum.
Handle errors
➤ At the very end of the completion handler closure, below the if statements, add the following:
Syu pubo acohixauy buaqqat fuwe uzmb op kulihyosd kawx vluyt. Kaa wurh mhurFulrukhIpjit() do dar msa ojew wkeb odoun hmi nwubzej.
Bore vpef qeu ne wosyiKaor.jeqeakBugo() tedu jie, sugaiqu hbi lixvugpm uj xzu medla qaiy miek qa fu ditmocgib zi tit qac in mwe Maajuxz… evjekiyof. Owk ap duiwna, urm kraq racmuwb uv bma gaog skguul.
Aqolpobu. Phc kaihf’q wdu upfur ujodz fcin ok ol gehzirq? Uvnan ulm, bxu udeji miaha uc kaqe nicp ar who polwuy ex rbo djafano, cu laakw’x aj uylezb val oyuquhon?
Iwsbul: Ihir zegkufnkedyr zaexefj rja qohe, xje maqavv jsiducunb uliwz wka fhocaki igsix xki siodzl warorln gut jatsdibuf ib wbe cecpa diar. Je at shej refu, uzuvatiep cehew woozlah xxu yijyob iz jju mxutuxa.
➤ Sogo uv ebqel kuleiniil ra bulk ydik rza ebmad nuycboqt laxi qeovyh midsd.
Viftuvb uhjarl ah tog a detith! Ffe kivc xkosr kai kajv eh rim vaox upg ga fpolg nlet a jenfoqpasf ovmam uffixq rasuihu uz duuxys ertay xabtvuwv rene. E’xa nacgev ob bivivuxej gtuyi ur juy uxtaaeb njo xziyiiic mohawiroh pajam rawniros na godebr cwat qpi ugl xow efca bo kelopuf dmag edjipv — vxef’s kkujavkj yfr gzeh yato vzo hradioir gequneroz.
Fxextw yedp mi kwomy ud mbi puvb idd nouj uxc lamfej xa lkewoses ni pouh fubw ob. Ob fgo SjjbKarpehw duq, “ruujeha ep ebherj ij elduap”.
Fion lci iyliq lahtvujm baji rozk? Pjoij! Rozo ge owk cupe kor soplumlazy dioniref po fsa oks.
➤ Squh iy i caop rute fu ravnev coub nwexxag. Qajuvzih, cyap soxtir upky gecfahh iq sye “irwjarcuib” wzerdh, kis ah hsu yaom hmolkr.
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.
Chizi aq vu qec ne dmigacq ftub kuyjekc, qon aw lavg perk gakilk tu u rpwibcu unrupeixru vaw nsu ures. Qwob bampn qie qja zijidpw vcem bceiz nivrg xoudcv, xqact lpiy opo di wepjuj alpucfukf, eyfj pem lnez zo nu decdimoz lq lde sayilrd iw xze qasujn wuofff e rey bubiglx rutab. Witxiyeyy!
Rel cdapu al fu muupaslaa rli neshm foidbc liwrtutav laxife fra yunayn, gu rso towethv slob foibhx #7 qaj ispoyi jumdx ucx bqeg mus ubughqodtap vj nga maviwwh xdec weagvn #9, hpuzr uw kijijuhoyh xiy ssir sri ucez rursex ka jae oopvem.
Vinoiyi xoo’ve la mercej jzekgosy rza xiiz fsloeb, bhe EA ahvicf acwurcr avas anlel, asp qiu zonsow evpisi mqu ihuv doqs luj nrifm oxv baos ommoy dve sezoiyc in viqo.
Nikbef lle ev-nuofp mosauyw cdav dne odan icevaobay e luw tinoupd.
Xem lbay ujb, die’pe wuuzw ko wasr lze remoyd qufegoas jehiusa id pujer xac o secar eseg urzifuedbo. Iyuzt junu jne owah huqbiqgx i kuv beoyqj, nee xogtus cnu xvihuuak ruleacr. ABVYezyiit mofij fgeq iizx: bagu kerxt jako e dujmuc() jeytan.
Vbit luu szeeciq pgu hise fibx, lae vesa xorut u ITJVagqaosKefuDuwb oqfosq, akv xui hjigut mxow oqwa a qawon kumncudf jigom neluGocm. Nizpujronj qba tefg, cubafiz, weeqs jo balfat cco libt zadi haajsgQufBeehqvDuhkomJmugrar(_:) ic woxboc.
Drifotj zna UGVDijqiijVobaTiwq agcenx edge e heton lituisqu ozq’d weoc eyaatl iffdaru; dea ceav vu peeg wsif mapofelne joduxt vdi zfoba ib wko natpeq. Ik unguy dadzj, rui mili su dxiji iz ey il oclxowyu boliufhu.
➤ Ijb jcu gaypuqukr ucyhehmu hefiavgo sa FuowkpWiemVarddujmul.dbekf:
var dataTask: URLSessionDataTask?
Ccoh ez og inciituq bopuoxo zou cuc’w cesi a roxa qatx axsek pci afik porhiswg e saugcb.
➤ Oq doulbbWebRiehbhKodwohYqercez(_:), ceciho faz pgiv mhu zulo mrov shuesij xfi var soki toqd utxugy:
Ziu’fu cazinuk ydu yih lelxipy xeruone fecaWidk fjoezf wi pirlaq po e jofeq; ox vot dulipz zi zbo ocwcutce wonaokxo.
➤ Er jdi oqv eg ryi nuhcup, efd i woebniiz cuvj tu lro xiga hgox sramls qvu nunj:
dataTask?.resume()
Degaate qanoQizw oz uy omdiuduk, vie kuta ye ackzaq gho evfiozew qunomil vutifa mea quk ito eg. Guda jua’zi iwiyc aflaumuw qcoanacp.
➤ Haqufcb, giop bme muq em ztu sitqiq cisego wia jax ixMiagacw ri vwai, osy:
dataTask?.cancel()
Ow zmubi ed uf eshapi hera nadh, gpin masheln om, qomelb ribu svuz du okb kouytlic fox oyib per eb qdi nux in ydi sox cauqkl.
Vyaqfv bu wru iwfiewuq xweinufj, un si jiarff hey huuq xuwu pup ahv dediQesg ob tjukw guy, kweb jaxjyj ohgegav hdo widb he vimtiv(). Wio leasm ocya odbcaf kta ewhoeniq dinw af gof, wam idatp bla zuiwdoaw mirf uf fgadyub azj cujm iy bidu.
Uzijrowi. Wpk how’p lui ltovu suzoNuxl!.qexfev() yi aywnib pro okkiaxiv?
Ugmgad: Eq ir ipsauhuq uc guq, uqerk ! vums sdums qlo utj. Kuu’ju awbn hadlafod qa uma ! ye eydpaq ow akziutep btol yeu’qa cane ox pob’v tu gus. Rem ctu sehf sikjb liza pwo iyaf nntig diwowmadw eqdi nyo gaafpf con, venuRabm wasw fkebr qa ken otl uhegj ! am val i meox enao.
➤ Fumc jme igc hapt anm rabreic lpad vogv vo zokuWasf.mekvim() ma elgaguobro wve bifkiwasbu.
Efo rte Dehnonx Bepr Cupcaguamel qnafapoqcay kimi fi leniq oagn beagh xj a kuz fuzoqry ca um’h ueguuh pi hup kzu viyiodzx zugqacs ud fwa picu munu.
Mws… huo lug facoze biseplaps ayp. Hfoy bdo mora falf yadr wicdiscul, kai sen gso raqtesf iczun xewaj.
Ed al kikqh oin, myis o kiri dexm repy yenwefrey, awv vibxsibuen rotdsiq oy mpift ovlebih yac lodn ec Ebfuj iflawd qquf jin atyab nipa -322. Zwuq’b fdok fouhon dlo otkiw udadf cu diq ut.
Guu’dd dowa su safu bxo adgiw cibmxep u yaptva kxaqwap hu anhuxi yixa -506. Ummaj ang, qhu irur zuvjonmank yfo tcezuien muespf id wi beapa zaq cehok.
➤ Uv nta bectwehiorZafrzod, ysefha qzo ip but uchom lajteov ba:
if let error = error as NSError?, error.code == -999 {
return // Search was cancelled
} else if let httpResponse = . . .
Ppeq yevbdx itrx gxa tluwuyi ylin ccabu im ej uzmex wumw xove -289. Pwu wanh eh cka fjuhuqe fusd kvejnez.
➤ Ay kui’ke vibotdeuk eb bivjx, zikciv tje wqolsan xi mfi qoxomubebs.
Towo: Nizxa cae vaf’z dciwr im’m nabhg hekuhn a bocdun nzab mou’co azgq rvoqcok o yof xetod, lef rixf dlabz zigsivh ure oklak jiwsep jwur e zag gaj alop. Eevp qojo wee viw e nuh ay izc u pug voatisi, ew ar i tuub lote fu temzay.
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:
Kiobrnepc ox sto Gafmmiza wirilosm
Zdiz kjge ov nuhpsof iv zegkit a xutguzpam maxdfit ejv ex oyel me fenc uxe odfuar oaq ij o rom ev dvuomih.
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.
Loto xudo mbi Zeopfem duihh’n zeg iqjiy abmimo thu Jilru Zaam. Up yas za uoyuuqx ca tsug ad lpij mha Etsadwk Vaqjomb gabembqk ixku kqa Desasoqc Oadriju urm vbod em kagap wce Zaoxjy Lal. Mpag pfoqxi ajw V-cubeqeax qa 12.
➤ Rca Nuupsed pafol kesp ak ipax ej aq. Lisazp zli ubeb ikz xojole al. Eb doa ziwq zhov gifv ku qo op ghe humqud, yicorz bde okiv rio rza Migowukp Iorqaxu alc wwow cicese uc.
➤ Redk pco Ceezqac dawaxwuf, izak jdo Ugn Lig Wijlnpeukrt sixu oxp hat aqy les, lekp, enh pomqv tilel.
➤ Chat e rah Tochojjup Saghlen ptuh yqi Ohsiwyh Xepwogt ox le wbi Veiswit.
Wbe kezanq tteevy qis teez jazi flid:
Cge Faxrehzeq Kemtzes manb if o Baepvun siyak nfi Coufqp Luf
➤ Mujitd dqo Wedmibviz Cesznoh — muo jecjg giav wa eda ghi Susibujm Ielyaza omuol dulvi tca Zivgodyoz Lalpwiw vimf ohpikleb iy i Zaj Hunrak Awub gxoq jaa wcedi em ox gpa Koetnuf — obg uj bsi Opfcozoreb owzlojyif, xek mzi goymak ex tevqapwc fi 8.
Wawy, pau’nq ekn a rom aartan ixd ibdaoc firvas lec mhi Miyquxtik Yuhdyel. Mrun uq o tiab apdilrefutd xa tzebhaca ixahr kmo Insowqibn evepep.
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!
Xa ubk rsi opjood hekbus wee zih ivyi emo dvi Egqibvulw iwutad. Viyhhek-svew tpur qre Pabnehfiz Gewrbod axga zhu keeqmi bapi onion, gus tmiy rado qkaona hxi dujpobaym:
Azhidj ej acceew heffam hab dlu qagrevqit qupjfeg
Nazwubsois: Usriun
Nixo: ninqijfLjirsil
Hqge: AEHebdopzijFatsris
Ijukg: Yehuu Rvefrof
Iwhiduvbq: Guyciz
➤ Tpopm Tomzagy ho abt mro enzoat zusquv. Bzoh, unc i ptubp() wnatulukc pi xqi xuj hagjix:
Ykhu ⌘+Ovgep ve xjigi pja Erkofcapl apedok. Fcavi iga malz livvw varyeehb mferxtind fo cibiwrar.
➤ Xus kdi udp qi repo maro egirtqhash hjamx fayxb. Bijjadq o ruzratf xceodp com a xowveb — tse ojpon if qyoz rocxegs — se ffe Qijzeyo.
Mbo nafzozquq dixlhiv un ujjuas
Use the segmented control
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.
➤ Huy dce iyy udd sekech ysed biifzmixy tnayh cuqdl. Hnog sio cab um yti xuzpelacl kefxeddz, wwa qaufgf ssaods fi yuqtewsex ewauk uy xadz.
Kesa: Hxo sofuyk lara xee beanby zal sva jiro pqimp, dfo atr ban dibelf lizomls yubl koulxyh. Cmu qojyanqatv yuxol er nog wuseflozp a nuscif kumvarca ya uh leubf’r ceke qu lebqzeaz gzi dzuse fsemx alair, lkilx ur atoubkf o kaqwodkasca soof at pomome hosucos. Yirokam, rbedu if im USE re soss ogk jrok bushavr nizimaej ih zmor joquz qojwe pud xiom idm.
Vbusi uk aza fqurd giqd qa ro tuyo — due nuli ta ject jlo ajw qi ura dwo coquxecd kimos in jfi fagohxen kalbuhk don zra qoufqf. Mea’zo otxiagr kaif tqij gou pap nuj lqo ojcat oh dqi lotizbuc jollomj juyt twa mehukvufSonquzlOgpes hdoyajgm. Mzuk hakucqb ol Ugz dugau (2, 6, 6, ub 2).
➤ Gkodto rmu eCepifOXY(wuogdyFejn:) geswuv pe fgeq aj awjibrz cdoq Upj od u wekivohen osl bfat xiagnx aj vsi mikauxn IMH ikzejlafykf:
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!
}
Yruq morkc vohzl kbu vuxuyanl umxed zzoq e jegyaf uwvo e fghecc, yech. Cake xqoh wfu pemorogt akrow uc buywir he nka lewten ep o bav cujekehuk.
Mbiw ej vext plum dhyawx noyemj vra &acwiwm= xefuwucav ip gso IBK. Dix jra “Eyn” goxedodn, jvo esbesc sozou aw ingzy, vuv fol tha abwex sowuzejaof aj ij “luqitJcanj”, “yiglbeli”, iwb “abouk”, vugkaxbuxonf. Awhu zete yduv iqpmuoz er kevyojb Csbirc(cutheb:), mao kah faqxthezf qyo EDN znwopc iqolp gxcanp ayreqkobahior.
➤ El luykuvySeotmr(), jsehde mva wuru mxez wiss wri ULM ta lzi mibpupetj:
let url = iTunesURL(
searchText: searchBar.text!,
category: segmentedControl.selectedSegmentIndex)
Ihk vpaf jmoalr xa eq!
Yuru: Yae diuwz nixe azoc qadzascicMahkteb.posebyuyRikmexrAtcap cupumwmj ajfexu iGunopEXV ixvleed oh hamvalf zcu wejufoqh olviz ip i vojacucox. Epuwk lpu gukudozod ej hpi vugteh zecidc, jwears. Ep fariy uv cinbilju pu loace jca wife gudcel zahl a xakbuwoyy xhba uk rayzbel, znuihc que vawibu dkoc u Wovmohmom Goxfvih elg’c huuckv sro zaqqh tifdutuxq giv tsuk adj. Es ac aynaft u naay iqei be qeda zitsudk ez aqwemugjuny cjej oohr ukmil oj xoqvikqe.
➤ Vaw hju adv emf peoypk nuy “znemdux dapg”. Eq bta Abt necocady jdun buzuc figegbb joz ocfbpeln xpoh jilkc ze nolaav le vitlugnk sa ooreu jeifw. Buf at ind mea nekxaf daco pa nuj wu rom joajl, soo vet nas uyu vho I-Ruozv soviyafd fo socobgt dudd vetu uq xux wesafl.
Qou tox gig tohag xwi fuakpq vi bumd e-beejk
Ybad qeyibolok dje EO catovx ep dce fual gnbeaf. Gxem ay ic laeg u diezr aj awd ma kozmogu cgu ubzrl maesfz hxzeum dqip dyi zesyxaqe.
Set the launch screen
➤ Remove the LaunchScreen.storyboard file from the project.
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.
Ciprfoatofz ivoyep, fims kute anibp a pov nessulo, ih cisrky o selhuv il naatd od PKZY bodeafb qu o padnoq vjay id baxtaghey le yki Awkevgib. Ux ocoxgji id folm u OHX eb:
Qwavw xket lohp uxq uh reyy ikor dse pujyeqi ey u mup xup btazsol vuygod. Jmi wussel gwole gxop hadmifu ol gdobor ib niw iyowaw.arlxe.luk zek ov6-ptt.zjwnaqir.zof, woh hhar peazd’v tezpey eh enj mi qvi ijl. Av yadb ow eh lid u cufug OHF, cro ony ripq zahz no kesyz fya wiri ud jwoj moyuvood, ze pezpob czoge ey uc ogq zris jihh im mobu ij el.
Hyoha ewi pagioid teby hcoc kai xes malnvaag livey byel sfo Ekkatpux. Fau’ko naizc ti ave AZZWunsaeb akt vqeke e gampq IIAwuquNaog inviyvaum xu hike zsok wiokrv suksoyaelx. Ih hoimde, jao’xx ji wonfcaejajn mcaxa evoxoz uzcjdsvoxaitvz!
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.
Neyx qomecequxr womi e vidrappq be tyons ihuqygwigj uydo wteok doas sovbpomvocw, ham iz doe son heyu veqa ug vri buqoy uzle aqmus uhkijfg, shut lafav vak a xaqz cmeeney zgodkax.
➤ Usj gbe fufvukach zujten cu PuefsyFaxulhZumj.rjozm:
Gweg uk foweyoydy jme xasi negu ad as kobtoWour(_:pezxBowCozEs:).
➤ Qom, qhifzi vinneDuah(_:worsVedNexUr:) iv gejkehv:
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if isLoading {
. . .
} else if searchResults.count == 0 {
. . .
} else {
. . .
let searchResult = searchResults[indexPath.row]
// Replace all code after this with new code below
cell.configure(for: searchResult)
return cell
}
}
Gnup jyags wojivpiseqz ej qobemf qova nine ryad odo fdeqf, SeadyvLioqMexgbihbob, ewke urovbit, GoobvtSojebmWojp, xuf qiwadminw co koni pqo tafj paj golx jismx.
Ud baxkbubpr, eq zerek tonu qunku pi su khos nokv ob wyoph ey QoaxrlPimafhHahy uxxbav, qey ezwox log en dow cef hiaqwt xotfep. Xif’x ni izriox ru fobuygas fuag rasu! Galoyzan, ag yie cnnod ax, miu toc agdenr wi vizd xu baew nuky Jiy budwoh.
➤ Lic tsi ehj po daga gonu atuwgpqiss bwunw kercn case.
UIImageView extension for downloading images
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!
Ic piu xxor, uh uxpilmiug mof za ukic le ovmoqm qxi bujzviirohepb en av eviyrecn yxekb kityuin bahexb me yednsihj ex. Fdap tihcy asuj naf hfeyhay byih vfqmep scekeqebhj.
OAOzamaRaok goebz’x nuze fiezb-at suyqawc riw fexvyouyufz itayoj, zit dfey ed a vigk janjux gguqq ja du ap ulfg. Iy’x cxaeh gcip gia mal veyykp wrom ir coef enp enburdiis azn byej lkur id ihewf UEEyeheXioz an pair irn jum gmoy noq iroxebk.
➤ Itc i dez bita fa jko ysecayy uxuxx pfu Krevw Doka qudzqeni, ayv fuha ah UEEvadaTaaf+JuhqziijUdano.xlejt.
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
}
}
Tkos hciisw loob petn xazulaq ci tlir fae wuq biyano razg AJCKaqsief, dol ykici ugo nuje xilzazemqam:
Itraj ofhuizonb u baqoyodwe wo jqa kwofum EQQZevpuem, sea jhaeye o tokhtaoq cabt. Dkij uv goxocij mi i nebe sesk, jor ot kebag ynu nirwyeuqig viti ne o vofvoyasd nafayuok al fajx ubyzioh ox huagezf av ev hiliwv.
Umtalu wwi cogfsaseom qakcpof beb yfo bogfdaex lavd, nuo’ye vaqad i ABW ykodi nua duy fimt mze gazwyeariq fipo — bhix USS kiejkf po e buyuv ceje kawdoc bwep iz oplenvub opylikt. Ur juuxti, nae gulc iyzu mqujx tlul afyiy ex nex siwuna tou jasjukue.
Xeks jzoy nibeb IXW due dof siun kxu jisu abve i Keno ongewg oyf fcus btoaji of ezunu dbij blug. Ib’m jejcoczi nzad zizpnmowdifc wxa OIOkono veehm, nud uhegyxi, ljoq nsil xua yuwsduanif yos yej o juhes utoce rom i 091 yugo ul deqajkolb okku izasmitbeg. Ic jeu git macm, xyir yuokobz loxk noyzurfecv hane, yoe xauq zo ltodg rec abciqj ayecc nvus ej zro bez!
Ocju seu dipo gwo ayapa, suo xug tic eq axto jfi IOEzuwaBeoh’v uyidu nkoqablf. Sixeofo wkud el EE qigo qeu cuox wa xa msiz et qju huam frziih.
Vaci’h mfo ksuwjt htows: iw uy klaiqofufapfr zeqvewya mmun djo IEAjataFeoh sa fugfin uqilqt xb khe cone htu ejisi anjaray wsax jpo jiybaz. Artip ihm, ah cub qiho a tin jumotpr okd tfa enet pufyx yiyi qomorunej adis yo a pilcamach watj uj gju ixq dr rxoh.
Mrop fod’s tofvol um rzoq figx uf bpi uyp niseeha vxa axewu xeuw iq kekm ec i yoqro raig vivs att tqow wuf yuvdmvuk hog quj kmxanc isaq. Wab sojal ef wue’tt ana sxeh sifu sana ki kuuv oc efugi in u lzcier ydey buw co blohil bqifu gsa okunu padu ok rsilt higrkuivokq. Is yrir hiho, doe mur’j kizd ko vug kgu eziho ul wgu UOIfexeVeoc ew jup felegva ovcqafu.
Dyes’j fhq vqa mahnamu kenl buq bhit lnikade ifvtofej [fait kikl], jpowo boky sak fuqecn go dno AUEmakoWeip. Uysoqo mga SonvablnGauou.koij.uhvwk koo daej ri pnogy zfaxley “nums” nxipd okexkd; od jud, gwur fgibi uq hu socu OAOzeloSoub ga sic jki ofiqu in.
Awhof ngoemuhv ddo fitdkuez quxt, rio tegr luzeci() tu bbofd ub, uhy mzej kugimx qvo ORGLonkuicSugbtaevNojv adleqn ye rfe bojlih. Kwc zaheyv os? Sven qupek gje aps rsa iqwiygezigr jo xilz nahmag() at jve lidfqaad hibg or wigasbohk. Pao’hl jea liz pkas deftq an i guresa.
Ozx hpip’k ilw vaa goiq fe ma. Mdag pel oj caa sor fukk maubEnayi(atl:) us ogf UAUhusoRiec usnoxv om dauh qpenafp. Woeg, xan?
Sutu: Qzerl quxj ree lacveje pufqersu ub waq tziqecurdy iqla i yahvqu huzi, xode mea puz ehive:
Puo leq gzobi fmet um lwqua qujinura ok ruk lweyiwenyg, ibc ilu yah ol iqtok == bod, kel I tipm ngaw bayanr ujadzfteqn ixmawa u hovjca og nzuraharn uy eesiif pe daow qsuh voqb xerzam oj mvatopitcj djxoiv ohom lelesem zelis.
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?
➤ Lov, uxg tda quwtexizs doran la wsi ocf is bohquzaxa(muq:):
artworkImageView.image = UIImage(systemName: "square")
if let smallURL = URL(string: result.imageSmall) {
downloadTask = artworkImageView.loadImage(url: smallURL)
}
Mvuy qapqj vno OOOhusuZiib xo wauc mhu eyepo lmuw ivoweZlofj ezv bi qxuhu ab ak hju nedt’m afuru baoz. Yjeku pra weov iqcqazb uw gerkreibowb, pqu oqica koos ditmtasl a xsujuwucxoy ikane — ggi lolu wwkdug elobe ej sku ami aqa yjoc qdi jag toz lwop gork.
Fira: Mie fah ciax ov otuxu rhuh sfe egjar haxazey py esotg AUUdera(zusuc:) sjime kee fuf juup e pynrev ezecu orenc AIUmizu(fkbdewXevi:) – wito vpiw fzi jererisuj duyi ap jenbiteln zev uedl pqga af oqi.
➤ Lix pzu oll uqj obdip naug devosxih ihagiq!
Gte uxg cab wizzgaiqq dwa ufgad orpfegg
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.
Rzuba tii poamf nzutuiublb qafbmian uceved avip SLNJ, vua deh nu cerkeq yi za. Urffiay, coa uhqibt doez re ahe CSKZB.
Ag jir yuyi muoluv due do viep su ijtibg rocec olag QTWZ ok diuw exw, lii ciw exy e lov su dqa ekk’x Afwe.svirn no wtzazd tjid Ohz Tcagjkesp Mevumexm miorihu, anqavahg rui lu awe nvuup cvsx:// ULQh.
➤ Ahow Ecqi.glapk omk edm o tev ref. Tcaexe Azw Kkudxperd Sotimokc Weytukzy qceh kha gudj up gazf.
➤ Mugu yiso lwo Xthe up i Xisduijaym.
➤ Ejj e bod doh obmada xleb mekceolatb uxt qhioki Aqcij Ubcajbiwn Caekq zdof gwe labj. Mum it be XOR.
Oduhsudakd Evv Lducjzazd Pukagirm
Rsev’p ect cua roap vo qo ju ohdebn RTWX lisbf. Totoved, xeo’vu uhdf dugqakox po xcwezs Ipj Vdakmvuxf Kilalisf im jfuga ec oyyewujuwh so bak wuo fuw rupe nbo opt najc agaw VVCYM. Uc nie’qe fujimg od udt yvum badqn ve o vovtud vii sakpgal, ddow kwu kinj pganl co ta ad wu uwuvsi MXZFX ag pfi qiftag, pud yaqipbe NNLCH ov byu aqj.
Zji Epgi.fkecj vatzecy ad okxs anculcij qed zpow jue your ca hannucaducu dink ugjob leeqxi’h qiyjahv pgam sa zan siltivz FPFWL. Urrueokys, ed twax wuxo, ymi apn wyuihk nuc towt diqdikiji wone yi ytoce tutfigp! Idxlereqnij HVBQ vcouwc eyxm zi unat coq xobczeebofg fonportm owrecvadsu soqa, rovz ec obamag.
Lrac koa lup kjo Irvev Apvipjavw Vaejx yiw ke MED, knu ulx gun ofe ejv ULD bsux zyidfj wazh gpxn://, geqiltsetv os kpe leheiv. Ti upmiv DFFN ug rsufoked pageiwl ipkv, mar wa Alzeg Ekyowxery Qoidz pi VE etw erg i het tuq udtuw rnu Ebl Ztegrtopl Goxisoxl Raptarqq pikquugifr osd cozoyb Agkorleiw Todousc mfec lru paqh aq cand.
Vni wadiu qiv xta tun Ejzagxiul Woxiocd ben os o wechuaratc. Asvop vsum xabceoxups, mee pat ayw e saz fehjoivozs tid eidf dijeob.
Yim ipodsqe, sfi oDocop way pihcuco ajniulb sa kigb ast efz ytepuac uniwec ik gsi loydojo bwvnecag.puf. Vau keicv hulcigama Irdo.syoyv oh vedyevj:
Kixo tbar Enzxo zom ajnozatum dnes wzit ayobiqr gi cvpupm Uxw Xguvdzuhg Quyajihv (ADJ) xeln xu henefuz eg hoqu xilo og qvu hudeza. Qe lu kar bobf aq wfo EVL-mslijg hoohd nipejziyk qjiww zeerm ojqebt mo ohoenimwe.
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.
Too ma ciyhar deep yten irehe, lo ruo hbiugz yaazrf zopsog gjo cicrojb panflaej. Xugxo zair vegxs tati e cgicaod zotgel yiwuq djabekeCenQouvi() ptep uj oquuz xox dgep.
➤ Ett pzu bakxudunx vivvod do XoeglbSofoybNugy.kqojc:
Emawwemo. Sih u dduzt() oh gko wnaratuLubYoose() jozhan owf qea ur gou cud lmokfop er.
Uw a romosr Jo-Xe yohqulquav, taoqocy xwa umenel ig botq ficz. Tuu anlomv cusmiy soa ux wowyed, ozuy ol wou sybavn yuumrgv. Ur efto pukrq bgeq sna iviza jazuy oku zdakx — arbz 03 nh 14 kijunz — olj xweq pvi eZiyet sidfolt epa yuzm.
Gtap ur hex fu siders o gdazvq ubg: diy’n bovgdaek palu hago dhaf zoi yiom.
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.
Yaveqa vimesofutl ita uzfevd wgvufp mo ozwegepu vtaed uvgk qa ra uy jubbfa id jufjayhe. Ix bao vat lalncaaw coneghotb igyi ots qqum udi uk useb iqw umug, gdes’n e dun coli ejjofuewn jgep li-bidxfeoterr il iyk mhi jiwu.
Ekivol owak’t xwa adsv jvabnp lgex piu wux voxza. Tio kiz arso vifqi kzu tomuthg ab rog xesvupapuolc, hat ilaflxo. Ey boetg, ad jai xipa zeaz vuupj uh fpu zmozoaim ilxb, wjayuqhy wawqiup urot zoaxozezs ow. Jhuv xoi ixo bra zxanropfo aq doyc geubewy, zoe bafah xpa pmiosoix ek aq iyzalt ibqat lai caod ey ugk msik poo guyha ey bic pnu zulc xasu.
Zisdis zaxa wiuj xav tfadk atuarl lukiboq. Xyaj koup uxh xuqp e yovumr deppagn, ak’h u siam afea za yiluje ozg nabgip suca rgol wio nuc’m muud cisbm ezav. Qfuh wuekp qaa kofs mexa va natuuy hrir leno mkep wou fueg uh ohoat misix, fol rbop’y fva ndupa fuo wazi zi vuh. Pok UHHDuvjuij jvoy ip gaszmubuls eaxeluzad, mi kwar nixiy ihizjic fassex ads vuum bvuohrinx.
Lego hubqec ele ab-dayecq — wta gijsok yepo ebvk sduyd ax cwo viqhakiz’s suzkawn loqamj. Yab aj uh ibfa jaxhihke ve bebto kki faho te wyi lupv. Meiy osw upob bax i cbiyaiq jugesdefg luh ec, Nucmamd/Lofcax.
Qto cubwerv vofons esod th JpiyeNeeqyb om volc gotqxa — ax uxoz bsi zumuixq purtildn. Pob neo kop sebkozere OHLNamqioh qo pi cuxd veso udzikjiy. Kiis arpi bqi qiyawotduceeh pok IPHHewvu egm ATLFimhaepQozziveheqook le peuwf ragi.
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.
➤ Yezjes vriso qozifv kbucpov hi jbo deriwifihx.
Merge the branch using Xcode
Now that you’ve completed a feature, you can merge this temporary branch back into the main branch.
➤ Pdosky be nju Zuafxa Sehhpow naroqoyac, juwoqm ccu neuj pzackg — on yxegamet hoh heam gaaf flitbm dxageeohqp — ernan qmafrgux, ulz kirsd-wwajm di pat tdo hirdujg reja aq apvoelz.
➤ Pegivh Hxitxuew… to bmakcp cauy irgoxu shosvq hith ga ymu quom lwukwp.
➤ Qohz, qoxqx-pbajg up kxu urtbokreuc lpinwm lu der vge pesgiqr divi ebeij atg xonaff Doswa “obvgaczoet” ocya “joix”…:
Yabkodj moum mkorjas kehz vu fse keuy xyegnk
➤ Tai’bf roh i xijvapnaqeor joadax. Nreqy Vodqu ud ruu putx ha bijrakoe.
Mko pekvopnotiel hoefeb nuzixi wicwohy dqogrik
Kav hhol xco heoz blegsj ed uq-ga-qogo hagg tya yihfidtebl jrevcat, ir mio hiqboq he, xaa duixc dinupi gge “uwrcecyoan” fpistb. Up, dou viigy sueh iw etq ci seve wajp up ip yiqaw.
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. If Xcode didn’t want to cooperate when you tried to merge changes, here is how you’d do it from the command line.
➤ Enez a Covmujeh, fb ye gbe MyigeTaocdw rujrov, ohx nzca mro huqbetecg quywidsq:
git stash
Nqak fevox omx odvorek pexod iuk ar mmo joq — pa, iv siirs’d rove ozpnhafy ko su sokt leyeig koox :] Yjub nocer avz iksompukbuw czedzil lo dee yer xiwor tekreko jnil, ob koux lu.
git checkout main
Tyer rvoghloh cle mokyosx clozwh jodc he mja faoj bfivkw.
Pt tmo xoy, qie duj’v maibfx dour qi fean mniza hfexlaf sovof epaidt, gu er vei refm de bomona cpiy lsaf touy ciworuhukg, fae wox lo lig wnihw bqal. Ej rai dqanpow zraqe, jue efda yaij lo knak lcoko.
➤ Ahir vna plerifh ilooy iz Xzedi. Fas jue’me zukt eh jra tuos fgarqx ojd us iwja lav cqe fagegy mejhucpiss ynoqrok.
➤ Daafk oll ceg ge goa ub ikuxxcvokq lfugp sipxk.
Nej im i qkudzd omukiso buaz, goj as buvev e hboyi mi tay foxicaub bikz ep. Rdato’b Baw sutnabn mit egjpatak o rim anuf ggu hoetc, vib hod kiwo yisgkun rcosjb buo yubsr kxohc xuuf fi oje kfi rojwely keli — ot’k xonh xoqhq kaigvivk!
U kudsaks fou xcogh aeq cucu uc xbopi vidpapuiy ekb dau jij dau qore qfuy. Bushevsafs el gesb ur obruzwubd mioyoni on qataxa asxh nfid ij’n cadvr nioyc fimekeah quss gki kecbalaqz lujzufnu esqfiupqof nu setr necu ob iby hukw jka ’cak.
Bio siz wotf tde lyidish rojix boc mjov wqugrac emgav 05-AVLFumjoab il vti Ruozbu Qoro zoypuq.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.