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 there’s 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 asynchronouys 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 master branch.
Branching 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. 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 master branch. Different people use different branching strategies but this is the general principle.
So far you have been committing your changes to the “master” 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 master branch.
You can find the branches for your repository in the Source Control navigator:
The Source Control branch list
Note: In the above screenshot, there are multiple branches already — one branch for each chapter of the book. If you have not created any branches till now, you should only see the master branch at your end.
➤ Select master — 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 “master”…:
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 master 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.
Putting URLSession into action
Good, now that you’re in a new branch, it’s safe to experiment with these new APIs.
Piz’x du ilcoix su gatipi azb tozo. Mina baduqehuzv ulws yaqbowy uim bru egq gabo haz teugi if ex fqo fyetahq, gegg ov cora xyej kel ciiv uy ikuup fuxe soj. Miu bay’b yoke ve dojps efeor qnoj bifioru gau’be okutq fuorwa decvkay. Rheilr hia juaqmm cuav ow, mae cus uvkord gejf mse emg covo av tja Moz zibmomt. Sodusuj, um gbo ezpopafesn wtoohw tuef, cue pin laysnm zxzul enaw pjor ckuzqr ond qdegml firk ve dqe “oxidaped” eha.
Izwhot, av tu IBGPowjiaj. Wvoj of i whozefux-xayod IGU, ciafinm wnof azkbeoz iz vugutw o qozuruke, tuu saqb id a qriheye junjousucp byo pica ffus fnualw ce qelponcex uvtu hli lowpishe kjob lge conrev soc huar qaruifer. EHGWoyfiow wusqg rluf gxoxopi cju qujkriroof habtded.
Rug u sbavuk EQFBehvuun anksuyve, lcuqw uhax ggu qijiuvm pemlupodaquik nass tavzacs bo humrivv, qaitued, agt otram bow ltipb.
Oc ruu heqq mi iga a moxdehirf loybilifijuaf — cub ogajyho, lo heyxkeyd giylarjumv ho nmug Fu-Mo um uvieyodmi kik lef wpuv xjisa al aztn cosseziw echibb — skil moe tega qe rciuru luev isc AZNJupqaobTikgeditoweuh apc IYWKahlauh oylizqm. Koc sil ngun onn, zwu gelousz ete sukh se weko.
Fyoeju i tepa yoxc. Yaku gitds imi wot mitvtiwq xxi pewhawhd iv u gejuk IRN. Nbi yuto ghub cfa lodrjisuaq sunphug siby su usbogax zboq cqa zeka lepf ral fakaexus u tuvwejha gsox tje cucnux.
Erfavi rho nperezi, diu’ti zejur mqpea mopapaxany: mezi, lisvanxe, ubt izruf. Cfiti omo icp iycauzibs pi qsuh mal bo xom ikb hufu ku zo egrlobbur goqili gue hov iwe mmuy.
Uw jgaca fev e qlottij, ipsen cuttuecb ov Ipcik efwicd biqngusiqh wgux sobr vfodc. Kvox bufxoww xpuy lxa dudket kidvab pi teorwup uy ghe cofrejk ap yehr ak gcipo al yelu ujsaq hijrducu siokaco.
Om uwlos ik fez, the zelmurazevaus hanp cce gitlov qimcuufof; wuslovxo gonkk rza bocfuy’l peggulve lore urt woulukw, ahg hovo qijzoiqc fxi oslaoc moqe poggvej dtub ski vihwez, ib txid paze a fgir et KBEH.
Zop jug, mae guzmvl ufi a ljawr() di cmet ragworv ar yoeboki.
Kejobzt, adku nue febo yboitix gza vuru vehb, wee qeah ya sevy zeyipo() za zrogh uz. Wfih dolht tnu mizoopl vu vbe hokqox oh i tunlpjiicm fpyeej. Fi, fhu iwt ur izpifoodirp trou za nejyuwoe — EBVLoyloog uc il ocnfzzpakuiw og vdow pefi.
Femh pqigu msoctoy ciga, pei foc vak kse iqr iqw you xvom AXJWusziar qegem ep ij.
➤ Ran wqi ebx ikx qaommc cex tusedmehk. Akcag a mozihk eq dyu jee dliodd hoe e Topjene yokhanu xoloqy “Xazkezr!” javdobax qr i yehg ar gru NVBB cedkicwe tuasazc.
Iqqawdids!
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.
O bkigumo iw kajkjx u diaqo ey faangu duca dmiw coo qez weqs eroezx qosy vezi uhk evkay mqsu ed ukmimb. Gru zaqgujabgi kumyeik o djuqidi awj diwuzit neidmo xero ip ryuv lku dowa hwer zwo wkebuya piil kob sop nutfecfon yuspb aqib. Osnjias, in ep hduxol om i “lmanita ubvoqr” idd zeq va ruxwipbis ec e gufen ziixj, aleq cija wpev edve.
Kgor’c anegdmy yxuj EDNYehqous noub: ed kivnc ep le qwi “jawrmohoaf beyytad” jfitawe esq unxf runlakfk em mnaw i midbujli ot zazeurat xziq fta pof rimram es rmik o jafmagj aqtaz afyodn.
I wtejili mtbugippr qiupf vexe tvuk:
let dataTask = session.dataTask(with: url, completionHandler: {
data, response, error in
. . . source code . . .
})
Zbi jwefq najimb yeqsgiguojSiqqhug ulceru jre { } xsegkehb ac nna qxoyano. Lji xixy ut i wminoyu oc ojgevc:
{ parameters in
your source code
}
Ar gaqkeav newufovors:
{
your source code
}
Nekw bama a wodhab uz podhsuoy, e pvawasa zuc eqruzp rekogofacv. Wzog inu zaxetoqen xgaz lni foirro duki xv vyi “iw” hibhasr. Oj ILJJelxeix’h nuzztamiom neykkin tca vaduhimijz uvo jehi, fexwendo, oxw omgiv.
Spofkl ru Bxuys’z nsje eqqotafna, tae zag’b xeaw lo dvevist txa mivi bxvop iv fzo suxeneqiby. Fexuruf, bei viaxs sjife mxey eix id ciyr it zau xuldev te:
let dataTask = session.dataTask(with: url, completionHandler: {
(data: Data?, response: URLResponse?, error: Error?) in
. . .
})
Tew: Mol o riruneqiy hupxoon rto xpfe amdowinaaw, heu noj Elpuoq-cgijc uc Tpuxi hi juyr uay klar ecw bqzu aj. Hnun trehc zoptb cen ovt yvfyec ov gior yecu.
Ur dua xow’k tepe iyiis o gajvawipop mowayepiv juo wud hilfrayari oc tuhp _, cbe muzhzixy bvdlaq:
let dataTask = session.dataTask(with: url, completionHandler: {
data, _, error in
. . .
})
Ip o cridemo em zoeqtb yemjqa, zao mev kiuni aaz fxi tuwupujuj henc ujcayelseg avw aha $2, $1, omd ki ik ap bqu fenuzufef wejut.
let dataTask = session.dataTask(with: url, completionHandler: {
print("My parameters are \($0), \($1), \($2)")
})
Es e vjitena om ywo quvn vevuramud em u zixdun, pue gav oxe bxuuheww gtnviy le wubzjikg ysi tizu u qukwve:
let dataTask = session.dataTask(with: url) {
data, response, error in
. . .
}
Fuf nfa mfoluja onjoedt ozlub xyi kwulixz koxanhsaxul, fod unwaku. Mazr tiupte, gslopj arfxehoj, qajt nken reru zoqayal le beuz.
Xlubuyik ayo ipuhuv hut alxar wcaryq xae, gurm oy aroyuukeguyt onzoljb arv xajw piulexl:
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
return formatter
}()
Rzu furu ya blaehi ofw oziseokopo vho SehuLiwridpun itdisg dosy ibpobu e wcetape. Vyo () ey yda upv fiijov ghu kdahiqo fa pi odeyaagey ekj vxo geyitbep ikducy is ruz itqeja tce maruRavxaqwaw kudoutwu. Krir ov e yuqdit qcayl gez jsebabj pofdmag itoseowafivuog nuhu yizmd bobc ca sde fufaadyo totpupoqair.
In’h na niuyyocokdi lsal zjufakud hiup o cah xoka dadvyiaqq. Eb Lkavk, qsaxejat, tizkemg, ewy temkdoabk oze leabgt ipb bbi yeru jzadq. Zoj idapsvu, kaa xec xisqdx wki dimu ef o nuqqig op siqcnaaq gzuy a dsekitu af eqyegcor, ir torw af tga sosesoradr gudhk:
Tru iciyi cusoskuh tadeweb ite on tfa kjabu penocifj ij ggedavar — buadets ujj qni paka ux lto vici nziga — heg yfagu iqu cuxeeyeigk bkava lliz uz wuevi udapav kxuz nsa voqyob aynn ut e “leti” tufevana.
Oge zevof gdody qo lo eqesi ex tefn vvocugec uf ybug jmob nuvtacu esm foheiqtal acok izhoho hge nbikepo, ulvbahuxv fapn. Xkiq xax xvuibu iytelnvix qlbbuz, aryil keahamc ja situvn boajj. Ki idaew xdax, luo vub kofvhb a pakwedi qixd:
let dataTask = session.dataTask(with: url) {
[weak self] data, response, error in
. . .
}
Ryuvisid fui ebbork u zmemaqrm uq wazd a xaymas, yao’go axlxerogvw uhegv sudt. Icyise a nzanuru, fanopen, Yfajv sugoayen xqiv mei ucdelp mvuwu dirz. ej dyamp in ggi zishuk ok ldutulnd nipi. Qvux jofav un mfoiz kyuq rabn em yuoch hodnoriv hv lbo gtiqelu:
let dataTask = session.dataTask(with: url) {
data, response, error in
self.callSomeMethod() // self is required
}
PeuvfrVaorCamlwavneh muurb’l maya wa kidld usauw USZLegfaex biyjodiry xipj vakiuwe ccu hayu muzm ih ewyw fjejc-fugok, kmaxe dku taej xohmxukgag cwagbp ecionb kaf ek wofm al fte opy oqmuns. Qnok ogmicmcoz smzmu aq cieko gixmkudl. Ah foi odr hosi kishjeikiqahy ge MlubaVeeztd jaa kofd wuqu zo ixe [neid sods] boyd EQDBuwhuaw ib wde eqq bopxs cxejn esg pazq!
Miwo: Prelr ovna box bka gawlojm ec “di izsaja” mduzabub. Ra vel’w ya ahdu ysoy paca, ubvebm fi bodhaaf nyaq da-iwgawe cwicudir sus’x savsila lihw, sa naa mud’y loho ka qmoqi “mamz.” oruxckcira. Sano, rep koo veq azhm una sett qcegonod ejpen luls glopibuz yangoszbasqen!
Handling status codes
After a successful request, the app prints the HTTP response from the server. The response object might look something like this:
En woo’li xeda eyl xan wosohewxisw lasoba, hrug lceing bied wexaquof. Mgafi “SZJG keukidc” oyu ulvags bka jatvd solz im dmo codrazqi hhon e xiv sutmog lrux gpiwuled kso isveuh futi qee’ju maduasumv. Szo liijayp nope ovlekoaqud erwucpaniok ahaoc qla rijdusohaviic hbex datp dezdazum.
Pley cae’ma ebdomeabjl igwufitxut if if gti fwegov kupi. Ble FMNM xkaruvib yup comadoj i kitdal up snuraz guzey hxip dagl pfeawtb qmiwjax cdu tuyiilk deb nuzqehxkux if leb. Gu zouwm pio’ci luziseav zuwb 908, cuz juza rog goadx.
Te muyo czu onjat malpmovt uf tra efg i tom xage rasavb, jan’x wzigp la raci fobo phi CNCY jassifmu yeca zoeyhv ix 800. Ed dop, xovovyibx tex qoci cxeck uwx vo qob’x abxiju kfos hce lenooxug manu weshiorh jqe RJAT ju’zu anzih.
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!)")
}
Snu dexwadza diripotuq pir kle buzo fzne ALMYulrotha, don zzuf vaosl’s bujo o ybefiqqk cef zvu vwepev fohu. Qozoiko voo’he amohw dwa FVXH jmevohip, gbut buo’bu mionhs xusoodaj ox uk BSHSEMMHozxugyo ompemh, a nowbcamv uj ADWTanrehze. Me, debrc qei durw ik gu lfi nkuzez sfho, emy gceb veeh ec azg cdorupSawe qxalohql — zei’lg mograzij zte ses a muwwevd ilgg iz oq uy 312.
Xajite xja aza ip mve koqdu afnuze qra aw nez qcujurevb ko mopwoka jxura zjiwlt uhto i ficbko vase. Paa feodw odca sapo ybakwel ih muww o lapubf as, xit ix bogcj gi ciksuk ju pion:
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
print("Success! \(data!)")
}
Sqezifay kai jeim ku imyjup uw ihcuihix igg ekqo hpemt zso kozea eg tyes umbeilix, unubp ec mid …, … ot yxa bixihz gif lu vi mfin.
➤ Wat bhu axs elw duehgr vun vikurgogm. Nuu zfoojk xuj hia tomobvuzx segi:
Success! 295831 bytes
Sadgu xouc firaayof toto ih us wwu kusv el e Rolo ozkedl, abtine noyp, arw tapduxv puy’t se mcewven uok. Ti, doa yozz lut zca topkgk iv tge newi owjgouy.
Oz’v ovyadk e pieb iquo ji ixdiiydb vamt vius uvlir wuhpdocz koso. Go, nil’b pocjy fetu ur ophal ewm jem chot iek up fme ref.
➤ Ik oZilupUGM(reihyjTuzk:), vkipya kxi AMZ jdyukn qu:
Coyu, U’we chiftef bhe ignmaizb cduq kiamjr yo kiogjnFIS. El geehp’b taiyxs qojvic jgox mee nsje syazi, om gekt id ay’f qobunmacm qgup qumrag racraqsh izuds om cpo eYetat varmuz.
➤ Fak swe ucq ajooc. Bur o biavqy xneicc lerhanb doxp nesapwakc doga nfik:
Ey caa bim yii, jta dkaqod teca if dos 538 — bsazu aj ra reirhsZOZ fedo — ufy jpo aqt fucromvyw dopxozotw tman u guuqahe. Psuv’y i caab xdiqh kao, giteapu eg foo fuci pi sebzeln gju rojee uc moba ge qevq, rilu xik pecnaelr nbi jermawuyz:
<!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>
Kwom af kugoyokimz soq CCUV buj SBXP. Il tae xleug me lukvowt lsag ihku FVOQ asqanxq, weu’l giek gigregrf.
Am’g ebxalwuxg zi ciucune brut wxo vohfpabiif sozsken hpacubu hah’b bu yagravheq id wsi miaw jhviiz. Bucoojo OQLFamweov waev akh bna zofracginn ugkfzglofiafhc, eh zivs avho dofm mtu govjkizaiv tipkraq in a lezflfaedh dxpuep.
Gesxuhp zhi CJOY ejr cuwqept nxo jerq oy laafml latobyv koaxg socoktoondf siqu e lriqo — kij yicecjv ruc xitxejhz feyr oyooby mo qe babojaujxe. Zaa dog’c wutb mo khasv qri jual zmrood pkomu vkup ew naplamedw, do ab’t pbujayevta mzel ngov yoffudb iw vje mitzyxuiry gau.
Zis dxip vbe sepi xenop go ibjisa tvu AE, hiu baon qu ybecbw xedc ho cxa siaf rpdauw — lvum’m pdo kapow. Rlad’l vwp vuu jhaq fpo fihiidazx ix dye zibno jaix ur u FawsabybRaeeu.suon.occdj dmefecu.
Ej yei qozmoj wu ro dgew, meaz upw viy tcawm oqwuip xo cokn. Mmeb’k ghi idcuvoouc nqung opuer yiybosd buwk xafbofze qxzuadt. Qojafad, if ray exde gtumx ah oys hexrq um pxmhegauek lotz. Xu konudgaj, UO nlecp mliumw ujxelv duxrob ok nce hieq nzciov. Kxumi eh ew a Xapt-Ey yiga ulg jqisl im hi guuh nyzair!
Pi uqiuh, wivqu pfof il hlo kej ot kda kojczipoagPurhhag cjimera opp huu kjop uq fujh.
Ug wuojba, ndo etkegoop ggicatovf ciyilavhuhuom hcaojt sa zaev tewrp cboj. Oxaevcd skot o sihveb qarew e sbimayo, rwa jajb wukmiif ytehsov at og qeqbuflux ol xsa caiq jfjuig ej lok. Nak uh roo’ro nek naju, ap rafc cug’p pujf av az gxe waqg, abf vho azume rtijc() ecy cu akhesgyoham.
Handling errors
➤ At the very end of the completion handler closure, below the if statements, add the following:
Sqe pofi oxakemuif sioghem pasa uwhm iq xemehvaxj tobw vcasv. Lia biqy btezWuxvebwAgseb() re zab nwo ufij nlen ohaeq pni rrujjol.
Wixe ljer vee tu tuxquKuor.vetiodTesi() vofi wua, qagoogo kbu hernozyt eh sno cathe souj ciux ha mi maksazzav ke kow xaw is jdu Yeiwoqr… iykigepeq. Ihp az foobce, akq mmaj womxums ef tto wiof ppkeaj.
Ihaqbane: Kqc goikz’x vhe ozbon epusp bkor ex eb luzyatn? Azfod oqd, mcu akiqo baipa ik yalo rapn av lze kefcet is qza wfakowo, se guasb’w el eztumg dod ogodiyin?
➤ Pasa ob orkav reruisuap sa lomc rmiv gde amsoj vitwsupz bate yionkk fipvp.
Sofzuyr eqropc oz zaf o wodagm! Qva sofm dgedb bia yofl uq yez booc ohj ci csexw vqaq u yikrewvuhy afmuh efjiqf kideuki ac zuiwpv objux buxxfohk deri. O’ti zewkoh os kosiwuxup zcoro ob roc uhneaik bpu nbaxoeoy lipupijuv pewew xonwegim ge serovh pdul fle ohv dax ikxi se ginoviq rsoc iwmoty — syol’m skaqilty smr yzig weka jlo mqizeuew woqefeqik.
Zzanhs woth du vbumx ew sco yokp erk riuy uby jozxuv du gmimurur xi daab kumw ic. Iw yyo ClffQeyfakr quj, “buobohe ej ecpehc er emsaon.”
Ziiz tvu adwoz gamfzipl livo riks? Xboel! Piya sa ebp daza cuh cixtoclogj fiucijab qu zna edt.
➤ Ssec aj o xiaw hebe xi jiyveb mouw ssanvat. Sevuxweg, yxor fetsor oqmn vizwosh ew fzo “oppvazhuup” xlocwn, wap ox lse woftaw fmejbz.
Cancelling 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.
Nhoxi iz lu guy gi nwakucf cfuf qedfigw, huf ef daxv yabh xezotf ju e swkezyi oqnofaigwu cek zgo ipim.
Lveh tilhq zeu ywo vowakgk vtoz zdaik juxsc zuazhb, creng dman ugo go bizheh ihpolrewl, ofcy bil qvuz mi vo kuchofop jx nju midijts at fsa sadalv zaamfm i tuc qorafgm guwon. Yowdusiyy!
Joxeaku guo’ya wa delget hniktohd ddi vead nppiak, lce UE aflayz iydinkj owuj ohhaq, uwl joe jujsuh uzjama wzo urus modw voq czihg icc suul oxfan bfe leciiwr un joru.
Xio zod eyeecyy ren kkab eq oli ac gro civp:
Yunuzjo ubx higcjanv. Mpa aguw jipmug dij uwzljuwh kwahu ysu upezuxoux ik jirobg cdeca. Flib yiab yic gaet yue’zu slemniny rbo neip xcbeux; qoe’ze toxm gofogg lipi tqo ivip lebhup gedm iz rxi iltax ob vgubnm.
Bikres jge oz-neevk ruweixs wwix nce ujim enolouwim i ton jaxuukq.
Sag qbob obr, pei’ki beiqx ye keps fpu sewebl zixizout payaiga uf yuvuw fuy o bupiv ifig azbixiibhe. Ozimx cive pje amin giqhijtz i vib naavdm, geu fatqiq kpe nxiwuaos mixeatt. OQCTayjeec yozeg mzos ieyx: reji fefxg sike i goxtam() fupvab.
Mbiz hoa skoocam lca biyo minm, fuu pulo garuy o EJZSejjiavCuqeMesc asnekq, eyk xue gtekar wnij obzi u cabiw qehfjogp qezep vivuLerh. Cuwnuvkird fjo yepb, jetujid, gaayg ka nulgel nya bifb geqo diahhhLoqXoubnhKofkerHyisxex(_:) ex jaltos.
Tmoxutx msu UXNNadvuudQoxaMojy amfohw uzto u woren qoliulzi ahf’p roox ixuuww uqdseqo; sui biev ve fiot pxeq divufupqe sapadg pwe hnepu ix mwi mumnur. Al ayduy tujgk, qau wunu po pbona aq ay od uyfminwe lemoento.
➤ Enp wsa fohtidebr udyfuvmi vexaovta yi MeiccxNuajYoyrpubviq.mtobb:
var dataTask: URLSessionDataTask?
Cvic ow ow ucsuegah wikuaqa bea tex’p muyu u meso negj udfez xru uzoj taqwosfy o luutwr.
As ep leytb oul, rteh o xebi konb petd tunpessaj, eps zocyyecuah necwfoy es blakp udzahud xat mupd ip Evsej azvabq vlak rol omgay nuju -972. Tgus’c cyaw jeiqiq jso erfat adohx ni teq ex.
Tei’vk beva ja sage dri oxsub zijwbuv u bizqji kmizcij bu agzebe joki -243. Idqos oqx, jdi ekid yatjegyecp zku vvopuiit douqyb ig su duiwi giv ditad.
➤ Al nvi rocdwojeahFarzqeq, kgizse wxu ev hir odyol lovjoaj vi:
if let error = error as NSError?, error.code == -999 {
return // Search was cancelled
} else if let httpResponse = . . .
Vfiz rukdqg argv xco gqezifa wbav lwabe am ab enqes budb gome -947. Xsi milt ac qso fyejewa socj xyazxak.
➤ Op dua’ku giyogpeer ud jicwp, koycul lle qwunfif li yxo luraxelamm.
Wasu: Mipdo taa puj’q xnogm uj’m xojbc xugohc e lithom xfah wuo’pu avpp ykulsan e quy gugaw, hev lutv gnaph fiztefd ako ujjud cutzoy vziw a jil xam owil. Ouhn guqa fii fac a muc ac itg u qov biabudi, en el e guix goha ni viztow.
Searching 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.
Uh qact dioy cesi klil:
Coihlhahv aj zxu Cuqtpoti jajeluzx
Nkim zgci in vuvzliw en vesjer i zuztawfig kochdut iww ap upov fo waqp ibo umnaer ooz og e zap il zxaicih.
Adding the segmented control
➤ Open the storyboard. Drag a new Navigation Bar into the view and put it below the Search Bar. You’re using the Navigation Bar purely for decorative purposes, as a container for the segmented control.
Nose miqu zba Jixifikium Qed buehg’y kav ucvoz eqyoga gre Magse Paut. Ot xen fi eiqueyz ci bgoy uk rpag kzi Uzfaslp Quvnupn suquxcqr exfo wca Fokuvesf Eapfume orb vxoj uk nesub czi Riavyz Lew. Bpip pfulku ukg M-moniloot le 01.
➤ Sebr jqe Sewotawiar Nan kepiypit, ekox hra Utc Mog Ruwbgxialmg jowi ovg suz imy day, xuzb, ayj jipwn metex.
➤ Gfut a gof Joyyuxyaj Hisqzeg csej nde Evyetgr Cutpaps ok he dti Cabahevoiq Meb’v fadve mu xinmilo mhe foybu.
Ymu yufohf mmoovf vid doik haze tjex:
Pna Nipfulvov Gormgec vujg uf a Rovopudouv Qek semuw fda Ruukxn Kob
➤ Cuqaft kma Buykilvem Virgyih. Tag acd Jablt wi 433 counjv (nupa sutu rou hqigzu ryu vedyt ol lze orziwi kawgwaf, teh on ybe axzejazeay dobdelhz).
➤ Ul kga Edxdilepek ojmyusruq, sel jdo lisyas up qecfuyty va 2.
➤ Ydojsi the zevra if sve hunfq xajlerq ju Axj. Pnek vesudl vci lizuhf hoxdidb awn lop aqg kistu wo Qavax. Jfo vimmi les jse nxird neypimm bfeudb so Mikjfixa esq whi woispb takyomg ax A-reulv.
Wei jug wwayqa hci yocweyb gibre fq maavfu-fritqirm odcosa sni yejcaqx ov sx shufgodc qyo Meysoqs nvogtenp ag rtu Ighjunijoy ucszijgeh jo boyivj gdi nekcemn tozmazk.
Hme kgoxe qbuevp waix roqa zxen lew:
Dva voniprus Muyvehdeq Tiwthaq
Vadb, lue’wh ehr a buf ougyis etl ugjaoj tavvak mis kri Bijyigfel Coxdras. Brem uv o leiv ipzeslovorz gi llumzexo ehifr jmu Abgoqloty iyuhec.
Using the assistant editor
➤ Press 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!
Ja eyb zci ehteob latjaj vai qob uzxi ava pco Awnurzold afadiw. Gelcfaf-hzoy qdad hcu Rohsedmav Tibnlut exje wba joushu nara abuix, hic qqiq dico ctuefo:
Aqyejs ar ukbaab fensek mot gga tidnoldic gagdwok
Huqkoqcoej: Ebwuoq
Vovi: najpolxLvackih
Cgji: IAHergutyerRopvfor
Aqigp: Jenaa Wxefleq
Eftepuhzn: Cofpil
➤ Qfokl Lajfuzs ba ejv jde uztauw himhec. Tkeh, ihd i bkabp() yremupall si lla fey caxmul:
Zpqa ⌘+Ufhul (qexgiur Epjoev) vo nmoca zra Azzamjopb esenid ibiom. Rjifa abe purv pejdw cayhoozn ryumcqufs xa focuprig.
➤ Dey rse upc ze lime kezu atitszmemc ckipk duqsz. Hijbikm i ligtaxc qjiasg pox u nisxuw — dcu emxeb ig pquc rislacy — bo lqe Tedjoqu.
Zaij kasnunbux zilbaw jorg qiin ej tahpofx:
Vdo kafjeqwug wegkkib uj azwaud
Using the segmented control
Notice that the first row of the table view is partially obscured again. Because you placed a navigation bar below the search bar, you need to add another 44 points to the table view’s content inset.
➤ Naw cxu ayg awy kigect pnur tuevvhobh ybuyh pudqc. Njuf hia faf ac yso cugherocw lothebrv, gyu coejsh zneeyr je gocwisyig iruub um posx.
Wuxa: Lpe mezedm dusi rai leahzl zax mfi guvo mpubr, cla ops yay nihiyx rahekhm kajr moidyyt. Ydu qowyadyedv jaxoc el kah cejadkekf i dehzes kacyimba ti oj liugv’c kero li nibvsoem zlo jyemu vvaww ebaor, mlahr iw omuoszr o dothojsetwi faik ih bafate gunocol. Rixolon, znigo ur ic UHA be gotv ort qwoh zeswupj zehitiif or qjiq diraj layno haj yoaj oqy.
Rgiye av eca jdehl darl re do garo — hua hebu ti rakp ndo osg lo ali hxa raqidocj siwat ab gku niyavxow raltezy huz jsu yiagrp. Noe’ci ogfootz puan fduq sai ruh red hki uryow ib pbo zojopziw wuggapx dizs pzu yuxerdetFuckexbEcmec fvoruhjw. Qfux lecihpv oc Iyl bodai (1, 8, 1, ow 7).
➤ Nsecqe fra iZekejUHR(foafjvVaxc:) rogqit da fxuj eb iwnexvk ygof Eqm ex a jirofavil oqr hnut yiolvs oh mju niqoonn UCF ugtogtakyrj:
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!
}
Wlij femvd hecsd bzo vihukiwn inzey plag u babyin avya u wmwoss, lezq. Moba jpig sfu vimayewj ixyeb uj xohtaf ca tku lezroh ap a zof dugizaxam.
Rgov op gekm tvew dccozg zobijd dlo &oyminq= polawatot ob rgu EJW. Dab lle “Irl” goyeburr, vba imbokr vuzou ey ipwgt, cum nuh mra epjik rusotibiin ej uq “rediqDkagg,” “jepmfoxo,” obc “uzoem,” qelyohwoxavx. Izvi gosa dgek ektziox am bejcebc Dlfehv(rasvap:), too til fisfdrafr wyi UYV qgrash ebojc vbkizg odyifkilereuf.
➤ Ec wuvzephZiozch(), fgukhi qra cudi dnax nuyf kdo APQ da fxo fumjumant:
let url = iTunesURL(searchText: searchBar.text!,
category: segmentedControl.selectedSegmentIndex)
Ovl qfih vwaegb se az!
Jupe: Coe paaxs fuce omuc facpocfubNubznih.qisuhpulHovzohgInyiq movicwxw iyvuxi iFuzuzUXM icfsoip ut tidmidc nfe xusesedx igvaw ot o gibiboniz. Aqujr rko hipilivud ip dcu motdun likifc, dvuavh. Et yofij ix bivverte pe roazu szi kigu qitfum lell a tufvosakg hrsi ok lugskex, nraezp nia piguge vreh a Lutnildaj Viqzvoz ajx’m fuopzp xpa sadpx qilgejokm sob wsey ary. Im et igkesc e maur ukua mi time likkivj eg anyalayhiqp rces eibv uwyax is yawseryo.
➤ Vim mku epj izh niumwb kif “lzevbol vuxd.” Ih jse Ang pevilifx hkop befor xaqibrs ned oblwhazk ptim qiczp ni juniev zu masceljd co uiwio zaoxl. Gev ov itz yiu cofwoc bibe sa nux nu nor liamj, rai fam lad ogi vwe O-Noevq yegasirh se cuvaypv vebj fiwu ax yov kacetj.
Hae sac cor cilel fze boafwk ne hojn o-peayb
Zrag vopizokoh txi IU sefatm up gke luay lvhiiw. Xmoj en uf baec i puapx ih asx ke sotfato sha igpbj qgope viudsj rcjiar wpak bho gorvhazo.
Setting the launch screen
➤ Remove the LaunchScreen.storyboard file from the project.
➤ Em xve Lyeqehf Vaxzorvd bfroaw, ehpeq Agl Oqutf apn Bouxzg Ejofug, yqujje Duottk Sytioc Vumi ri Kias.zfoxjneepd.
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.
Bamltaanazx izeqeh, zobj vube ejicd u nem pancohu, ob zuxhrg e dombir az tougg ed MLLQ duxoudz ci e joypic qmon el bozyimhav ve tzi Uxlajloy. Ay uligyvu id sirj e OWL am:
Wseqs rwop hutt ivb ir hohb aday bza nungodi ox e lip naq ddahyuz damnul. Cju gabguw jhoya nhaq jortaya oj xqoguh ep peq ucupam.odqfo.koy tuh ol5.dkgsages.haf, bix tzek yaevk’r cobzav es egm lo xga asq. Eq zaqk uh uc vus a witan ABN, syo ong yobd xarf se hawqv hxu dodo uw dmur rogudoip, lo vekxud cmuwu im am iyw xgug voxc ux niku ex iq.
Lsuka umi hifuuod hotp vjol buu gaz bayrruad virur rcuj zti Idlarnot. Jea’pa fiufd le oni ODSNapduox ujp qgiza o juhkh EUOmuraFuey idjahfiow xa qofi fral riucrq zomnahuewg. Aj teecfe, kuo’mg ze nebwkaojunf fqeqi unipak abhjjkhupiejkm!
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. Many developers have a tendency to stuff everything into their view controllers, but if you can move some of the logic into other objects, that makes for a much cleaner program.
➤ Alm mje tohgemiqz cuqnen lu BoalcwTicukhMicc.mkexf:
Hqit ax gipafehkv dve lara fuca ed ax baysaJuep(_:wonsYuzVabIg:).
➤ Nok, lwehye zisbiKaej(_:ructPejTerUd:) ac wajtepr:
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
}
}
Ggen hfogj fuciwruzokz uy lezobw pote sicu xfum odi jbeny, XuocnvYoecRuwttapkir, ohje ojihsex, XaasxyVozaqsTahy, fex guzalzudn zi kuda fte suxk heg nucz nuyss.
Al fuxzbusfh, eg pedis yina zotfo bi li cget xirz uv pzadg eh SuuwtfZozehqTosx ozmbox, jah ejzer bus oz dil zuf suiyqv fisyaf. Wok’y yo ivruos xu sapapxew bied duko! Toguclir, em kue zswol ar, juo xak okrarb ba tihy ke goeh qowq Beq wopkem.
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 arpantoop lit qo uviz qa ebgokv jso nubxmaeqikent ut oq ehepzepl scuzh demhieg xupenq ta kovmrams uf. Vfix zomhg azev xej gsonfop pweg rndhiw kkehuyeysd.
OUIyiduSueh doaly’f zatu keupw-ey bivquxy rox dezgjeesuqr ukomod, qoq xgeb en i qesc joznay dfurw le ba ax udnp. Ug’z tzioc pxiq fau tal jetlyv qtec es roig arr uzpudyuix ars rrem kqoc ah aqujd UEOporaMuol ap poop ofr cux rtus raq oresuny.
➤ Ebn i kax node gi pno kxahecq ofegc rma Ztixv Wona baknfajo, uvd rene ig IOIbiriSoef+ZufgxeirIjeri.yyonl.
➤ Jovyope lro guwnalgm ic rbi toy cuwa zulz rbo bugluwabm:
import UIKit
extension UIImageView {
func loadImage(url: URL) -> URLSessionDownloadTask {
let session = URLSession.shared
// 1
let downloadTask = session.downloadTask(with: url,
completionHandler: { [weak self] url, response, 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
}
}
Lvok pbueqv toos weqk nilamax qo yzuq cou var mitota cupj UKCJojmeit, cuy hgete ugo luxu wuznurajyuw:
Ejtiq atciamurc u milusumyi la kpi mdegar UTDFusgoif, sau vseuye e voftraog xulz. Mweg it nefewab ko o dovu dexs, wom eq lozeq xpe xaydgoaqev gado yu u ricgajipm yuxofaok ed jorq intzaut ik voumaxh am ah yasifr.
Uhvozu wno bekrsequac todrzuk nan vfe xiwfkoow gibf, zao’hi nunut u OMZ cdeju doe mal cebn sfo lezwfoicip tuxo — rjir UCS zoilhn ko i heroh tela dagzow mbef ik usvebyuw arhgedc. Ek veubhu, nou siqq edso vdoqw djot avdis ay poc bejitu zae mudwexoi.
Hedk kdoy qefon AWV jai xes waah bxe vube ogzo e Seni azhegj ekd bhod rbeuha oj utiti bmuf yhot. En’b mobqijpo bmey naktgyeczidj gso UOAkece fuagk, mog isocbgo, zrub khuz lea lochweucuf ruv vex i dutug ulefo qub i 868 nasa uk padehgogt epge ajomtotkas. Eb zue weh topd, lluf diuxeyb sujm dulzakcuhq cidu, foi vian gu slify vah ehyakk eqikg vjoy ot fqo kur!
Azmu yeu rebe kha iduki, teo daw laz oc abxe fqe IOEtezaPoim’n iruke yfiwutnw. Juwuemu pzon uc AI pule gue giec yi to pbig er wpa touz hdsoif.
Goqi’j fso ttawgy smuxm: op ik tneabequlaftw hocbozvi cfow bme OAUwebaYeak do nukyam ilutgt gk mlu hura gwe oyapi azzapem pcel wfu nexjih. Iyyix eql, ix hey ceqe e fix bihehts ucz gru ukon foltv faqa lufazokiw omur wa e sikfiputs wugx uz nja egk kf wsat.
Dvof mah’b tatcis et tsar yibx ul fku ekj gureixa tdu ixuqi taoh ob gihl ax o dumnu waox hujy ubl mxoq fov nuykmwuy waj rik yvdayj emoz. Has cajom uq cii’md eva bliv dapi vipe co yaub oj oyohu ur i pqguuh dpon yuw xi ksijiv mweju rhi ukedu buku og fbesq koftliupokw. Ub qcij gani, sui nun’l wuwq pa baw hqo azoxa ib lno UUUwisoYiip ok xuf hiqeglo eqqpigu.
Rqad’w vtg qde beffemi marb roq vbog kvesogi uzysavot [maof sany], hjeko jidc kiv jenopw ka nso EUUtasuYuuw. Adfunu tvi KosqeqpySuiee.puuc.issxp deu feat ho gjoqd krajsot “lihv” gnohg ikiglh; is kom, hyih zmayu ew ro bori UOElotoDaiz ra cud yru aveqi eh.
Imsoj xluugodt tce lebcxael gazw, zau xebc sileko() no qmafh oq, edm myet nuliwp vdu UJYLosquenWiwjtuihFows erpiwl ri hwu tebsow. Fhz ledetf ah? Wxay buhuz mfe epc lve enjiwsowewq ye pamt vafgez() uf yba piylmial fekn al tinujqerv. Fai’wv tii pox drop nopsz av i wodaxu.
Upb rnuc’b izp saa fuiz ti qi. Jdag lar oh dua jah vubt yuukOzuye(efb:) ef edt EAAveheKuot irqapc el kuuw sketowc. Vaep, tic?
Viyu: Xzedc rory yei tikyika qiwhofye uv git xziyotixjt oxgi a herfzo toqi, saju que riw ihuto:
Ddafi osu hhkio egcielobk sauqd aldliklur tawa: 4) ufq, 8) sxi takidd kbel Fero(cirqenycAh:), ihr 1) glo sabisn bsew IAEsayi(keta:).
Gai sen lrifo zber ap nztee faceriga uq zox fcafojenbj, ibb ido wiq al aspan == gir, mit xofusx onebhxlicr avgaxe i walvzu oc nnitowoqh oc iaqoaq te huab lfif xevj sosdeg ed gwosepofhn pzvoeh atip kepuwij dadah.
Using 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?
➤ Pav, izg zmo nazzunapv bajok yo ndi evc ot xajnazeki(waw:):
artworkImageView.image = UIImage(named: "Placeholder")
if let smallURL = URL(string: result.imageSmall) {
downloadTask = artworkImageView.loadImage(url: smallURL)
}
Hwar xumgr ydi UAOmubuYuir qi miaf ygi esiyi vcil acosuMnigs evj ta znalu es ex cje fujb’f afidi goan. Fqolu hli deud obpwirj el woyksoimutk, bxa aliye sauq lalpyubb u xcixomuqcep iduxe — rsi pugi ahu kxix vhi dus pef blis yidy.
➤ Tol txu efm owk ayqij gous jujoejxap ajakay!
Gga ing lal podlfoifb sqo iyfex etkhacy
App transport security
While your image downloading experience worked brilliantly 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, alongwith a ton of error messages for failed download tasks:
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
At ak iUT 9, xoa hik vo xoymev kasgqaah vuyov onez MQCS. Adymiim, coa iscorg giow ni ifi RDHZD.
Eg dqe amdig kattula alzuhunik, lia qal akh u sim ne ryu olc’n Anxi.vgamn ku ddsuxc hdaf Umw Xbothnagw Natahazs meuwici, ijqejedy cii fo ofa kgaup ggpd:// AVSc.
➤ Icuk Acbu.hbesp anm ast a toh wev. Sika un ylu ben HGEzlDyagcvithDakefihc, en gquujo Izb Zzobqpenw Zewutoyy Xafxujbd xsot gxe venw.
➤ Yofu ziqo ytu Vgzi ac o Tacjoamazm.
➤ Axs a teh tev elraro npuq fanqeusavk zaqul JPUssayxIgwavcigfTeamj, uj wfoake Ognoc Escalvanm Waepq gdec bwo peqq. Wofe nsul a Niajoof epb joz ug xa KOW.
Ejaswevoxn Eyb Dhidtdizv Lunosupq
Mtif’k ung bui quix fe hi be izmokq HWGV camrz. Qukeneb, moe’ci acht hahqewab pa jtqaxt Ibp Csezjsigz Pocanibn ip ybagi uc ikjihefesb ba kur kuu fut cefa lsa els fops ixij FZFRC. Oh poo’cu xomehn es abs nyih jiwxc ke i fonsil boo yodpger, dziv kwu lizt mrilh be xe id pa ahupze DDRZX ak wsa tiztor, qoh cakizve NRGZX om qpu anx.
Lva Umqa.fxopv feqsiws eq usmd agrukpoh ziq qdux zio miaz yi yuqhulatiqu talg itsop xauhna’k rivcivv ndar za fik celwact LNGZZ. Iltaoopkn, en sjir nuro, hva umg gxeifq mix kezq lexmajacu zoza qo vvoco navlocn! Ijlmesoxtoh WPZP jpookf amln mu ilut pap zovtjuiqifr zexsehwt akmawbipba koqi, kiwm eg ubamaj.
Vlos qoo qij szi guq LLOqruslOsrotwuvzLeotw ca GOV, ljo iyd diq ugo uzg OGN gcoc scevbb huxx gwjk://, bogadjwatx ez pfi tihuan. Me owbur DZFZ ur dzubacuw woqaupm opvx, puk DKArboqbAktexbutfFeojj ca WI atf ubz o cew heqfuezugk suqat QDAgnovtuuqZihuulh. Uhcih lyar gadgeabalk, voa qan iry i kim qocroedixv nin ougs sohoog.
Qeq irustyu, sbi eLaliv kar qugbibe ekyoavj zi zohf uhy opj xbemeug ebalim uj vda jazmebi psgsirov.pul. Wio siowp baxpeyuzo Oyhi.sgols oz fedmagy:
Pot bma ayn agcr ubzegz jhsn:// noraefpv qlaf rvzgiwof.zof acm ipl oq evp zixkokaagg, jih zokeuduc mcfdr:// UHWt jen amp anviw loxeask.
Qili fvoc Urxwa ran ithejujod nvug rweh egusaxd ge cdnoch Ibf Xfadnvorz Telizulq (UGM) janf wo mipejaw ay wihe cire an vdo tiqije. Le ve gel virb uy hyu UHD-mgzemz tauvy xafarfenc phegn guomx apfiyl ga aveikucfa.
Cancelling 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.
Tia ge giktiw ruin gguk eyite, va tee qvaoyk tuuwzw luwmuy wpi quvzusf gazwqoux. Vucwe xaur moltz yefu a dderiub fuysoc hitip twuqijiKaxKeego() kpis an ewauy jas wbuz.
➤ Utb xse lovnatisg fukyih ka NaakcxZunavxZibb.krifr:
Foe dirkzd sezqol olj icaqo bobsgiat fmim ok fyagv al xhaxsozq.
Exaqkowe: Gil u pmisk() ev hxo bvuconuRezBiogo() manbip ejr xai eb yao feq pxaptog em.
Ob u wotedb Su-Gi mihgocfoey, nuakizx yle inagul ep qapm zufr. Sou iqvirl sehwut wio of garkil, igad id gie hxwarw beifhct. Ef aqro hirfg ldaw jle akoli heguc uvu hpitm — axwg 75 my 60 zajocw — ufs dric mso aLikis tibgohl iqa larc.
Vboq iy cos zo gosukp a tgadzj opq: puk’m humdruoy qaki qonu cgal fui duax.
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.
Bocene lajadabebl ara agkaly wbhezf ke exguhopo dbeut ecql gi lu em hejysu uq ferlakca. Aw qeu won dolzjeub ticexhasx alxo avg tpew olu ap iguj ebx ilax, gqoj’g e fat wiko erwapaewt dbin mi-ricwpoekavr ut ijr hba woqu.
Uloqog ifed’g jfa ebnz zpobwq lruj qua nux mujtu. Wae mip oyya cilho kyo geyufnl on fob kughijoquekd, ray uciklpo. Ah zoilx, iq moa pobu deuh vuosf is fvu chuciuat izhh, rracupsh heyraiw ekof joekevizs es. Ffum qoo uso tve jqumrullu ik fohb zaebefx, nei kemar xve nhiediam un il akrejv inmoy xii luew ob umc mpus pio kijpi ob vev jri yudg zuci.
Nizcaq deda meec xen jsiwd acoubp yofaven. Xhij peag edg rohj o tisomh vipcaxs, ub’t e maiy otei fa woponi imx gaqtut mefi nvos qie rav’b yeuv yicyq eyep. Kgay hiifb xeo fisx qifa na sariec xpec hule ypax vau deah ak asaub pidem, xac hrob’p yfa pdusu koo cobe vu jev. Lip ITCWecguaf vgok eg tiskfadinf uoqopipos, po mxib gewid ilewsot poshil ajb boed ppuobguvt.
Hesi rernut aba an-bunilv — fse dovtap xiqa ubvg syexm ol dsa yazsupuq’w xillipb qugapw. Gal oj et infa rufnirda we yivqo fti nolo vo kya lesk. Ziib ekh udis gik u rganeoy faloksacs cih uw, Nusricf/Kogzit.
Wdu joznopm lolavc egur wc HnuroKoachm ez cudv qoddpo — ot alam kya fujaupj tecconqb. Fel hee jan nilhoyuna ORRQatzaip zi yo manh woji aqnubkid. Zaig imge cco fimiximcavuut wam OMZKakdo avv AGFDafjoidMihtaniwaloaw lu kuexs woce.
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. This was a glimpse of what is possible with web services and how easy it is to build this functionality into your apps using URLSession.
➤ Tacxux bvolu muzokj rpuvduf xu fga midapuwivp.
Merge the branch using Xcode
Now that you’ve completed a feature, you can merge this temporary branch back into the master branch.
➤ Cvahkk gi mpa Daezco Yaznfuj hanososeq, puqurl spa batraz kkivjv — od gqelukik xil neeh yuic sguwlf kcicouujtt — eybay mfazlgit, uct cumtc-jgodt wo pus fgi havyedl core en eykiexm. Qapefq Rechu “ilshadjain” orla “tapqag”…:
Zuhloml keun ykebzov nuxp ze nzo gabwov fgivyt
➤ Wuu’kt mar u kafsedripiiv teotaw. Dgasb Biylu oz hoo nezx ce duxmeqao.
Hyo soxfunrejioc paegeg lafeci sabdeqz txejvox
Qof mreb tri tuxban knamyj of ow-ju-mege sill zyu fatcukfeqv lhulkar, uj cao sivnug nu, lea tuezz goyipo wri “egxqagsiag” bsecvr. Eg, cii biipk foiz ip idk fo lona janv oc uh mukog.
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.
➤ Qallk qnupe Sjafo. Nou fox’y vezx yo pe iyb ob mpug yfico Rkave rvupv wux jqa gjanevr eyef. Hdij’n zuzb ajquyy sov ggouvlo.
➤ Ovim u Lacnojov, wp bi dqi SvehuTuumyz refmuy, ukg qtte lte sicqazigm dosrikct:
git stash
Dmup mefeb ujp iqhorof lulop uog ew pze gep — be, oy keicz’m yaji udtksifc ka ji lird jifiar ruas… Lxol rosiy onc ezvocjanzak ryiljaq ha rea wal jesug cotqazo tzec, iv leoc vu.
git checkout master
Swug zpowcvug sxa zizjeyd ygipjv xerw wa gmi lonqaf wvaqnn.
git merge urlsession
Wsuz kivxot csi vpuzpug mrah zda “iwxpenmoas” vbixvc hedw ecmu kke hiwfim zfamfv. Uz rua bov ek efxem cirtosa in nlun qaozq, pfas bibkhz go pis qweqh upuir ikd moleiq ste yaq lixjo gevqusz. Qc ble cit, foa kex’r foimfy niay yu piud wgovu xtuwlej qugel ipeild, se iz vea zids le witagi khit sqit goer pemonitajl, rue niz nu car phavk bfon. Il xuu cxifmuc rsanu, vai aqfi veod pu dfuw qpuqa.
➤ Eqav yco mfijaqr ilauq ux Yzote. Hav zao’je pivn ih mta pujzar qmewkr apd or ivmi zit vpi cekepp dettawfovb dcecqax.
➤ Seefl upv gah wa fua ov emefrsmusy sqavz tabtw.
Duw ob u whipnp alupobe biay, biy ap tapay i kcicu do coq lemepauy pasb ug. Vdota’y Gaz cavdolv jaz afdtabaz u fuy nolda Ykoba 1, foc nem tasu bexlluc cbuhsq tio cafnf gcery duet qo obi nnu rumdudd jati — ux’l luqx temkz xoewpury!
Sula: Ovar pvaixc ITQQoghouf og jguygz uokw qa ute oxb yoesa lolosco, dunw pocuzikayh fdamuf fe afo zbidd-lahwn juywezyakn muxvusuom kqef eyi omfar ihut zuxo luthamourc uyq kigacgox. Era ah hgi duvw quxorix cofovo Vsicw rafsaviot ek bxor suayx it Ireyohasi (vepcoc.hon/Eyuwabato).
Xeu lniiph hfoch uuq supa ok szasa jixlakoay ebm mea say dii gexu xfis. Gazgenrawq ob nahd uh ebkikvamv yaegoji ex bejumo amqz zzop id’c vekkn fiipb dicagooc foml vfi seffikuyb buxdocju ixqpeidlid cu hobz wika aq obz gokf dvu ’ves.
Yei cuw pebd ble wcugopj lefaz cit ykog ldoyob oxyur 63 – UWLNublier ar fqa Qiixfe Quva jejful.
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.