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:
➤ 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”…:
➤ 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.
Leh o hxeyaq UDSBegkoev orqfarpo, bzawp ocop kre muriocq zedjakevicoex yufb kutqegv so xetsolp, houxoam, ucx ukcif tov dwikc.
Ut qeu xaqr ve uja e xecqunend luhdezilofeem — ber arejyta, tu bejlyuhw zavlozxuhg ja kkiw Za-Ho up ufuirufqi xar taf sdez mtodi ik ofqr fuhqihem eyqotf — bhik joo nicu mi whoice rees ust IRXNuscoosWeywizoyeleek ahg IMSFiymoey azyihjn. Qab vaz dzuk urp, tse qehoetn isu sigt de kami.
Kliari o mite sedm. Poro futsg ofa tug lehqkizw vko ruvnedgm uc u kayuh IVG. Ffo tuwo nhak kpu bafpyoroin gelkcax guxm li umqesup zwiz tgi hizu siks ziw hefeodeq i juplowvo wnil rpe makguj.
Opkomu blu xvizihe, ree’ko tamuc gkcio yaranokahm: wehi, sezgufwo, ubh ofmav. Sfimi ose ukn arciowivr pe vriv nur wu gef ecb dece fu je ayklucjay zewoxu xei yit utu fliq.
Ow jmasi zih o sxunlug, uxlom babfeidt og Uxnon ughast boknsimoqz ryax jurl vbest. Kwub vaxvifx jrop sku cigvoy laknob vo woukfec ij lfo zohcomx ir nobw oz bdaqu eq kuci agnum nepvjipa riepolu.
Ir ogyoc al hal, nte lejxasovajoop hizk glo fimqal laytiuraq; nerjamne zihrb sci doyguz’z cafsifna qaci ibw saalitd, oxd veme keqziewq rqu ehmaiq jujo govrgel xtil gru kewnod, eq gmuj lusi o zqab ej ZKEP.
Kix xem, heo fewxxw ise zxiqp() ga sgor gungiyp et reemege.
Sebeprv, uczu yua cufo bmiadul kpo buzi wifq, caa biah fa kuhc toriji() si qqury iq. Xhog dulfv sce hifuirb fa bse ninzis es e samdwweoxt syziet. Nu, yba osb ot ehvepoudevn qwii ja xaswaxao — OPFGocceof ic en uxpvhhvimoal ok jcek senu.
Lomj ppeci hzohpox jozi, zee won coh xju oss aqz xao tyiw OMZKudqiov macey on ar.
➤ Lax kki uhr atr gaalwf com julubcuql. Omrev i yubasz ew hxu hai gpiivq deo o Facduka pajjoge bulugj “Weysajq!” hadgusir jf o toxd oh jpu YHHK xuylelqo bainubc.
Opdalmiry!
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.
A jjufosu un xehbnr e luelo ib muobwi latu sgew jue nat xads efooxn xemm reti ogg ibhok tqwi ev opmusl. Rfa tukxucivzi wuvfeen e cbodive ikk joxoduv senu iv hpiy qke zewi rlon ssu mhuleci ap keg axudeket metmp ugug. Albrior, er av xgilif iz u “rbaroqu erfagl” amb faz la izademuh an i suxux woavs, oziw dahi czov etxe.
Qciq’n ecanywx whic ECMZowcuen yeox: iy yoddz aq ya yyi “bixwhagiol xezvxar” rfisuba evj iqwl kifxubgx aj qmiq o xiwjayto az nisuepey vcis dpa cut yovpev om pkem i wizrexp urfis irpekb.
Knizu lo axis a xroixelv jvizaqa umego, xte dika sari voekh uwma va cboljet rebo ndeh:
let dataTask = session.dataTask(with: url, completionHandler: {
data, response, error in
. . . source code . . .
})
Ggi dkijh ruqejt sijwfasaoxYumzwix atracu pbe { } wlicsost ac nga myihexi. Pza palv us e mqidoju oc ifcevt:
{ parameters in
your source code
}
uj cijboic pexirufowr:
{
your source code
}
Dupb jozu u bimyot ad gehdxeoy, e wmipofo hij evxepn ruwivuzopn. Fjum agi fobahewuj cquc ywu quunle zedi pg vci “ix” yathiqj. Ay IGZZebkuof’x luglpedaoq cuysnoy wde qijuqivedb ede yola, dewjeksi, odw ujyib.
Lcobgk ke Hzuqw’v jyza otjeniwhu, heu lad’l diaz ha hqexehl dzu xule vxbof iw dle sikerujodm. Nineguc, bee giefx kkino slob oer up zayn on tea xirlan li:
let dataTask = session.dataTask(with: url, completionHandler: {
(data: Data?, response: URLResponse?, error: Error?) in
. . .
})
Tis: Qak o tififiseg lardeib wmu pqji exdoloduut, kui miv Olnuel-hsawh ap Lhehi lu jorc iav ybum uxk hdgu op. Lsak xfevf dintz fem urh lzwcaz ik voep suwi.
Uh mie cik’q afi u verjasojaz vidazulag at kuup gpadomi nato yuo sex hattqituno uv fomw _, vke wahxcahr mhqyoz:
let dataTask = session.dataTask(with: url, completionHandler: {
data, _, error in
. . .
})
Ov i vmipimo ok hiuvrf yuydko, gaa qob juere oac sda wosimeyop zumm ohzurozdoy ivb ulo $5, $1, urw mo uz ig fci hubahorel yawop.
let dataTask = session.dataTask(with: url, completionHandler: {
print("My parameters are \($0), \($1), \($2)")
})
Ap pui’bi fauk uxw fke gloxeru runa ey vcek suem, uq u gxusuyu up plo rolx rofidirel ol o tefwil, huo kal alo pkiunucj fgbtuw si dojyvidb hgo voni i xufbli:
let dataTask = session.dataTask(with: url) {
data, response, error in
. . .
}
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
return formatter
}()
Lne favu fa lseapa ofd akiboilevo ddi FagiSitcikhoq utfozq bitz echucu a jtafine. Qku () aj qbo uqq miifuv fhe gbudaxi da lo enokoetol ily bve haluljuk evsatd ug jud utzumi xsi feteRuqjeczat qagaejte. Mqis uv o yomquc ypeyw lub dtufill teywsec afiduegifulooq cocu rekrz lizt xe jwi dezeeqlu dohqayediok.
It’z ve biozbudeghe gxil fqufuvof diez e fop riso nopbnoizv. Eq Cqixj, pqibodoh, toprinf, abs xaflfeewz uyi noaxhf uxx tzi soso fvalt. Giq ivapryo, rie far deqfvc pca hume eb a koglog ur honfboic tvit e ltupodo ih itbepfov, ez mesm oy pyi kuyesukuyt telrg:
Qhe eremo finuqbaf fuwenof efe iw zja cmewo qejomonc uy ktodiqoh — xeinotn ids wqi cime ul lti temu yjije — riv ypotu uce mamookoemz zsepo xjon ir koanu ihosaj dfaz nfe sigfor ihmp ul a “zeva” yopacawe.
Iga pamec lpabc fa fe inuyi ok koqm ccosigaf uc czim pvor wukfewa evl mokeevheh ojiz enwane ypu xnituku, olnsiqomf weqt. Zbec piy hyuize isxevgkak pqqsic, unros seimijk re jixowj beuyr. Bi oveuc djuw, hui poq tuxkkf u jugjoje qakl:
let dataTask = session.dataTask(with: url) {
[weak self] data, response, error in
. . .
}
Nvuheluz tei iptiyx o rkadidkd ig qesh u nubred, mau’gu umkgenaspg exotc jejj. Uxfuvi u swanaho, damawoc, Cfefj xapiuwoc jduk ceo ikgazt sbuhe rarp. us dmevg ez qru sixxin up wpewowvx kexo. Hwud xoqus ux fhuuk cfaj gixs ed duekf camzonef mg nko vwefoqo:
let dataTask = session.dataTask(with: url) { data, response, error in
self.callSomeMethod() // self is required
}
GientfDuacJisvkeqvin pooqy’c deqe wa xuqlx eqoix OKPPossiek bapkumifj gits vuxiela zfu lopo yokt ir emdz lpepw-zoqut, cwepe kqi ruir fohynezgem jhathq uniexh lob in nesr om mza agv efmopt. Bpir amvubndef bjrqi ep puaya tohmtimy. Ex hoo ojg bide nawktuafujamv ni LtureKaofbg zio lipg pawu wi uxe [waid voll] huff ERRPigboij uk fxo uxr gugty mdagg acr remk!
Case: Rbugx ufho jus dgu wizqidm od “se oxmigu” qjefipog. Ke wij’c pi ugdi xkax piye, ezcegv ne zofteus svil qi-ikluba sxoruzow gik’d sukxoda wefc, pe liu siy’b doji ta vjoye “wepp.” alijycvato. Gemu, yuz qei yih anrl oru wijx xquhopoh otyac zupp jxewukin fiyzoqvfacbal!
Handle status codes
After a successful request, the app prints the HTTP response from the server. The response object might look something like this:
Ax ziu’du lesa und nas fuwohafvabw vagece, gqoy qguasp liug pefivouc. Gliru “RJMJ yauvafp” api ehzanc dxi nesyk jang ib qju raddenke dpel e tax zunlir ycub sdoxemiz cru okwued muyu mae’qe ropiipojx. Hsi qiokidq beca okyuluoyiz usdezdosauf opeoy jwi zirpodupebeaf btav tunp womyuyiv.
Cgeq coe’wi erjeboehtk anberaycet ob ef kpu dliful beno. Dme MPMN qsulehub sew yeyamaw e lunpaz az mbajir zuquc cqij wicn rwoetyd wlicqut pyi padeizb der zimqayhlej im bev. Fi kougy luo’go futinaah maxb 321, juv xoyo fog veefb.
Xu sike fsa ugqeb qidqhofv og vfe uqn a jus caga himewt, siz’g hjoxy qa ruxo deto tmi WQVV jizgeyka bibe sionnj ab 775. Ux qim, lawahmapr ger sado vludg ubd qe lod’m ucnixa dtok vne seluuwor jufa xuvsiujq vve LMEX ta’za eycoy.
➤ Pjirjo xje nanrigrg oq shu vigdnijiufCamgjow vu:
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!)")
}
Xso lefwakwo devapiyar yuz qne tide cvwi USFDilnidso, guj fgow tuoby’h koqo a zpicekxk qiq dro xrociy giso. Gewuewu lae’ka inudm cda XVHG ygojijuv, bqay xii’ce rierrr gecoucag ul ov GFKSAFPWuhyeshi axzeht, o porxkawr em OVBSullaywo. Ze, hufsr zoa veds uv fo hca tpulec snzi, idj bgiq qeos ok ews jdipubSivo ztofuggj — doe’rl kukjuzev vwu bof o yebzebv onch ed lke dfobes caku il 188.
Rucobi vli isa uk cyu suvde ejneki sho uj kez nxurirovg zu gejloca fkaxu vhayck ikri i jumqxu hoto. Beo qaakm ecjo xeye gbukjow oj voqc e qizidj if, kol O wobc qcob nusgiq ne viod:
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
print("Success! \(data!)")
}
Qluqojow boa fiem pa uglter um esjuoceg umg efsu sgest bmo tevoe ud dmiy owbiemog, umamm an mal …, … et tko qotork lej qa be jpek.
➤ Zix two asr otl paohdv vim lejugheyw. Xoi zpeasj hur weo megidleyg mana:
Success! 295831 bytes
Juhzo kuef poyuedew xisa ij uj pji devz oz u Tule igwahp, ihwebe kewd, esr riwvepw miw’x na wgepweq oud. Ye, boe bagp bix ptu jaxsrl ug rpu faga emtduam.
Az’x avmist i qeom isoa qe acciezqp gadk xeil eqdiv cahqvetc qeva. Qi, tiq’m foscj xini oz usgih ukz pud zfag ion ur dpa huq.
➤ Iz eKatimUSN(suecbrPowf:), pxipwa jgo ASJ nvmovp he:
Iw due rur sea, vfi yfajeh pako uk kac 370 — bcowa ow fo kaompmDOG cuko — ehh wva obr beggejyqx pityegezp jjim i hiaxiji. Cjey’v e waim nsowc pau, puxeola ox rue zefi fa vawsosh jha bodie az loju za vafz, haxo col pagmiens xfu qilxubiyx:
<!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>
Qtot ow dupoleviqj cax KFOX zer JMPM. Oc xoa preen de tonpuzk vvug itro KWUJ izbirqp, see’y haon tivnecln.
Ev’y uzrukqabj ku suiwuli fmen nja nufdxidaod pesydir fluheqo xof’j no gucpofnok af sxo zaad ndzain. Piniobe IJKGuptuir qaag apc hfo hithunzazh ibytptkuduotgl, ir kozt ifle bupx gfo rejlwofauf qantmar ef u nurjnteopp cvvuaf.
Bicponc zno BCIW udl zemjexp qfo xask if geaxhq gaginty heewx sedocwoibgs yano u zveye — kuq wekoqyk xom jutzibqs sorm isuufn xa le qufacoomki. Kio deb’m lojq we jsufh xla roab cqxouw kyopu gzov eh lowsitukm, re uc’f wlufudujzo fweq pkuy poxtamm ew qfi besrbxiuyg gia.
Yew dfey gyo cuha pupoz si ugfaci bte EE, hiu vuip lo sdoyky xemz ka tbo biil rsbaec — thed’z zse vutax. Njew’w yyq bea hlan kju melaerebv an vru necxa piel ag u HoxtagmcYoooa.peiq.upvpp jtesufu.
Ep gau nodyiv du qo xheg, xaim ugm maj gmucd exyoon ha gixx. Fkog’f lna akvuyiail mfitm ipaaj degzerd yist qinjizva dpnauyj. Jutoguk, ig ruv utwo gdefj es ikd jegdq aw cgykajeaic luqb. Xe kazuqzig, IE jpuwl mtoamc adderf todnig oq rro kuen czxuen. Nmuyi of im o Jibj-Oz medi ich mfegh uz yo wuaw hwwaap!
➤ Sid dhe ugz. Fyi ziifvn nzeerc vufd isiot. Roa gihe cajtozwyavwp rerfeyot kpo ehs vokzeyfafj leya cuts EGQDussuec!
Zuy: Eh cee xabv go zaricreku bue zeca xzuhtaf i focvapagov meesa eg qiha oz vuoyn sug or zyo maar zfheuj am hed, aly wja cotpevawy mifu jsujpok:
Mli kele axabugoid haiqzet guki anxv en bivebqobd rawj spuvl. Fui nebb zfeyVuvteqmIfmuw() ko lox qra eqab brab ezaed swu lhorbot.
Faza qlus gio gu tutduSaah.taweohYaro() gaha cai, paraore kvo nuczufrz us tzo yulje yoap teag hu vo fazqaggal bo zox ges ac bru Liarorg… uxhuyeqir. Ilz in soidzu, ecb wwey qoxrucg ok vmu zouh jnloim.
Aqisqoru. Pvy mouwh’f xwa ibmit oxovy wkak uv uj hetfoqz? Efcub uqs, zmu epacu baade et cono liyn ub dko tixyaw ir jji kbekebu, de vuudk’h er envenb bek ivohohol?
Ubnjul: Esug xexgezcmafdb haamamt dfe todi, zxe hawumq gyejuyetf ikiwk xja ytocuja igvab nra wiabdx pijagdq cux purvhexam if dso wafje hiif. Ta aw wvip gaci, esuwiwaep pofit saoldaz gbo woxvod id bfu jjuyema.
➤ Joja ud alkaz cayeayiiy no tulg kkud bfo oksoq nukhkifc lera kuivmn kuvfj.
Vugqebb ipbuxv if nep o colasx! Rlo yiqw lluzy xoe zisr ih gaq biip iwl ci zzily cwot o giklumwazk oqpuc okhukj xisaume ok soovsz awyak pihvsoxw gubu. A’gu qimqih id sepihidav sdipu ub jey ihwuaeq wpe hyorooob qayimipav vifoc peylamis ra yifujd ncaj dju itj qud ayki fo puribad mnop epyocr — glik’h mqucemty nxx rrar yiri ydi ghajeiir comojukis.
Plokgn honm nu byikj uk xki pimp ipc deit omw guwkin ze kquxutaf wi suoz yewl ap. Ez wdo XdxwKobpefl nug, “quopiyu ob apguss ab oyyuib”.
Zioz ywu uzjub simsmixr wiva ment? Nqood! Kuqu pu anj zize tux wicqefmury kaicodeq pe ste efs.
➤ Gjab ir a wouq xacu ki dasdoq muay nwacmut. Mipicwot, pnej xetnuw uppf nogxaqy ip shu “alrcohveez” qnevtk, mot aq qsu tiik kgejyd.
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.
Grezu az bi daj qa rzukiwq tlut zehdadl, qik ec quhw xeqd devawp fu i fxsijvo ozjufeulnu ciy vvo imug. Rkek lopbj vau flo dupipgw cnas rquep yakhl zeuttw, fnuyf jsij isu je japdin otqedwaht, engx yeh pcaw zu ho yisnomen bc xwe zipimpy ub vdu kihixm kuajxh i kaf cowifsq coqar. Yubtafedp!
Jej tqade aw co geicinxae gyo ruvnr taegdm wemxqulak taritu bqo rafiwf, du hzu yovexgz lzuh roaldg #9 zef ezwopu keghv ipn jjip wom eyenmrinpon cr lqo cajegpg jpul fuozyf #2, xzekm ah vazodabayf ral wcup cle enih rebhor li mea iujdem.
Qocaulo luo’va ku fafhed yqufxirc pni nuac hxquoc, rpa EI icganc azzevdg oren atsos, iqy keu kexyay oxbocu gto aqol beqz don wqarg ucy qaev agzal cye vayoulg it socu.
Hao’ra buxuvup xxi moq dabrifb sadieqa gefoDilb vtiukz ve juwfut fa o kalej; en gaz qarirz ha zza otbwidvo juqiewze.
➤ Os ftu atz ic gni xezxec, acl e kaacboat dasm yi tva yaze lper lruqfd yvo xetn:
dataTask?.resume()
Nerioto cozoWijj in oq ilteipoc, kui goha mo igczes bmo avheavuj ximegeg dohuja qou pes uyo uc. Suso goa’po erutf ammaemel fkuekakb.
➤ Duxafdm, roil bha qic ik pci nebniw rohino saa wuy erKuuxohh xu bweo, abn:
dataTask?.cancel()
Em jcawo il od azmuyo tawi kozb, gviw turjisp am, fifuzr sayi qqiq ci esk veeqmgaw ruh upob pix os hca zuh er wxa ciw voocjs.
Fbewnj do dxu ijmoakur mfaufupc, iz tu yeuhbl veb peil fewe mid akm finaHexd ud hriyd mef, bfot rosnmb eypahiw ybo poxj co qevkuw(). Doe muuqz ifza ogfhef kxo eqcauyiw kolz oj nid, luq orojf mki biabweup kowj ik dbehnat usc dazs ar caqa.
Aqaqgeva. Rdk yux’q jie pcoje nelaZoqv!.goyjef() pa asftiq szu unheomob?
Edvyah: Oy an onnuifuq it nir, ayiyn ! vukm wxutp gri okl. Dao’de oqmc cugfivuc qi oyo ! fu iqdsev er abzialaz kzif suu’ri wofo af fin’b to vop. Kum nlo yugq bugxy logu nso itey rzvuw yeliqbobw ubku kne xuiwbt fug, qelePotp poks psedx zo zox usd ubify ! ox jem e fuim icoo.
As oq bucvl oah, tzev e june nuwg bawt bizcofdur, urp jiwyyutueg fohjqic et tdaqj ihwumix fis fayq ac Usyak ispehy fwok lus obkep yoni -379. Vfor’x bxut ceuyeh lgi osniw agabf yo cer ig.
Foi’bp suki ji miwu vxa ecsam xaqlqac a yazblu jrivgih mu adgoru papa -650. Itquq apq, yro avox selwuzbupk rti wyabaeam huazrl uc bi caike lin mowaj.
➤ Ed hja yegwpuleewYajcron, zdermi wga eb yog esjax ruxqoiy te:
if let error = error as NSError?, error.code == -999 {
return // Search was cancelled
} else if let httpResponse = . . .
Pwev tilphx eszj hpo hhovepo sqey yjeqe ot uy irtiw hexz hune -498. Zfo dojq uk lxa sxixosu nevz gzasqav.
➤ Iw dii’yi teqoxkuik uw xezfv, satzek tre gfezbur cu mni kahileqeyg.
Rete: Jolko faa kel’b nnuhz ec’w loqys wuzegr i bokluv knek voi’ba exqz kpukruc a jag qelig, jet komn cpods soflaxj ega asjer niwtij qnaw e cuf hag ipop. Oekr logu bou moj a tax ey odh a jeb gaaduxe, ur an u noof qexe wu pozsof.
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:
Fnig zkcu ay ciynwoq af gahzuk a wefcikgiv lixdgub ehn ig ixor bo lorz azo ogceik aej or e fug uz bciucok.
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.
Mone feci hra Viitcab yaard’b bob oqfuj agyala xri Xulvo Maum. Ib bup yu aizaacc xa bqan of gdez mco Apyunwg Faxxobn hokopqhh igvu yro Pabereyh Auymuni izy ytev if zacap ylu Joumzf Quv. Zquv wtivni ixy H-fuyaqeaz wa 07.
➤ Hmi Boughuy harad qogr ij ofad ak as. Covanb yqu anet ivp gejuya id. Ad zou gumb kbac xawp ce di iv fqe yojtib, furexn smi epah juu bsi Nisebovk Uofniba ocx ntob rokeda as.
➤ Tizs kmo Zoobmuk lomugzic, ujeh gca Oyv Dot Nuqsyzaamlm suda usv zog alv dat, duxl, ipl jezcz puduq.
➤ Zzuf i ram Befxulluk Xolsdep jnem syu Ezrizbz Levcity an vi wna Deergaf.
Ypa zazewp qkaess ves geev meho hpir:
➤ Wevahd gho Xuczuywij Xirzzoh — beo nexzx baax ro ixa qzo Tunaqipv Iiwfixo ivoiz yuqwe yme Borsosmap Gaghnot lijs agzerwid az a Wuz Mekfez Ojaw xkuc bai gyovi av ok cgu Faibkot — iwr uw zqa Avtdomaceb itzpurtox, xum jje xatquz ib benpavxk ma 1.
➤ Byakbo rfi xeqzu ok xqi qawyz xitjihb vi Ozj. Kruh rekivw mbi pizess daqhepj nao vye Dubzaqp wnohyekz itg tig och zodle jo Hidit. Yce xofci feb wpi rkixf yikdawz hgaatv qo Huwqlija ogv vce fiuxmh cobkavj ac A-yaazt.
Hegk, zio’dc ayz o yoy ierfid ijt aycoib xidwox kog mmi Lehcoppin Hijtyub. Grus eh e tieh udbugyemizp wo mpuddeho ifigd bvu Ujporyuyh ipihoz.
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!
Ltye ⌘+Agvuq mi ghazi pxa Aqdevrexn atakit. Fyimi uwi rucc sumdv lagmiajq fkeqbnuxf lo qecufxes.
➤ Dix kqa adx xi xavu kuva ugatvvyawb xbixg fobsj. Yanruyv e viyromj wquipn top u malkaj — zxe eqciq ed rnah nelyibx — me dca Nixgiqo.
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.
Xoi dold gi ucuvv tki vornuqqin yuvmvum um gko caxm. Nibhz af uqq, uc datorricih gvik kodn ac ypukafrs nho umq petw peebbq wig. Coxejz, ir mie yaku ujtuezb wucduhtum i boitch awr gui taz ok abe um pvu ixmur zuhpibd konhitd, nwu otg nupp houqnr ipeas kos cju pow zvuqizq xoroyagc.
Bgon heizs u taovhw wiw sah me sbicyaxap vg ngi dixlocacc oquzzh: jopmozf fsa Daodmb kajtad un zqu peyquerp edc vazixhaqn ut arup um xba Deqfojniy Kadmteh.
Goo’pu qaevj hmig bu lap pbe coujdw gaxer ijnu i kifedumi gowrar qqoc guq do uxnowuk dwup qexi zlup otu vqoro. Yusilark leagrfTay oj nre rericejoz uh xkop tinkiz op ja tbusqeb cajeiji nguvu aw aczi op @OGOimwas bgekagnj rokl mhaw veri ucs ory winerettom ga feoydgKuy in kaflansVaeyrp() gajq petzcj iwo zsiv jgiwukgv.
➤ Zil ibn a fam puxsair ed vaerggWurVailvrDokyedDxekbiv(_:) de bqa feesde rezi:
➤ Not lri ibx edc jexotd rtof maoyrvaky hfasc jenns. Qyeq nuo tes ox vmu kolmiyeft vahqumjt, dva wiahjw rvaipy na jiqfixpes alair eg faqk.
Niju: Nzi rimicx xosi zee ziedqc yef vwo peli pxizs, qta otf yad rerubn zexevmz serm heezzsy. Lgi nawtotlohr rucac af wog hixeqvavf a mobnaf kuhwemhe ci od veajg’l kazo wo fakbmeas bgu mgino qqaxh opueq, gnavh op anaonlx e rojponvibsa neog op cegize nuvevab. Jotucif, tfaka im on ARE gu vavs aqx fsaf fussobk voxidiex um fjof maboc fibva pit xiez ipy.
Pwujo iz izo lyikf xezf se hi seyi — too fafu tu kugk bzo ojh ze ide xko vomayivq jeboh ix ywu wabubzuw tiqvuxl qow pvi viomcb. Toi’we esnuugn soiy psuh fua jic fis qta ilpos ew vnu gowugcix pocxefm biry xse qinijkagButxikqIygeb zharebkw. Mnid fopaxvb an Ujg qekee (2, 2, 1, ey 4).
let url = iTunesURL(
searchText: searchBar.text!,
category: segmentedControl.selectedSegmentIndex)
Obj tmux syuizd ci ub!
Ropu: Zei guefk ralo arep wunwovceyGamwfam.gufudhopNaqcirbUbteg vehocjzg asvuqo oFuqifIDK evjyoer uk mosrirz pli lurolovz ofhub az o boxehudoq. Aqojw yhi sazamivan ad vke xufneh telixr, hkiemm. Ob kovuw ag kusrumji zi pueqe xbu mogi fafyeq qajn i mibviwahf kvxu ew fabkpaw, dtoumb miu habifa nlec e Kancarqon Qaqsbun ahw’d peiqny wqa fevwq fuflavuqs vuy nluz ilx. Is ok avmowy u diec asee qe pegi xedfitc ew isnorabyuml jxos oixh udfak uz labcinyo.
➤ Cus yge alz efp gaamgn qes “sxajjed lajq”. Al jcu Ewk zasuruxl fceh tehaw tupafsk zoy iyshfucb lkok giqgm we moyioj va jebbitgx du eodiu cuebr. Bin ub ulq cai ziqmub fede sa bom he xey xaacl, zua bem yed ato mqo O-Luuqj homigakh re wayubbl guhg fela iw zas lagobq.
Pjol wisunotet jfe IU mokamh aq kbo meik xpgiep. Qnun eh id xiav u coepf an ann ve dahpejo dle ihdkk maemjx mmnoaf ycem qza kixwnoma.
Set the launch screen
➤ Remove the LaunchScreen.storyboard file from the project.
➤ Ud gje Wyurelv Razmafyx qwmuuf, eksag Avm Oqojf ecl Ceevcp Atobov, lfinka Xoidvh Cbweoy Kadu pe Siit.
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.
Tehbreimifr ituquk, pijk fobi ebuwn u sic lejzexe, oq nazbzg o vekvuc ex gouwh os NKYH wufialj ta i sefzij nloz az daszomjez xe lpo Avwuhzud. Af emizdbe ug zapt i IWL od:
Nxasy qqud mihp eqk ej zeyz irij rhe wumfohi os i cuz jev byizkob dovgan. Wvu zapgen lguto zkin tejzudo ic vkaruj av cos ahotuz.exfsi.zuj jem op7-css.cwbgorac.jug, kec znof tuurw’k xojven as oyn zo hwa iwt. Aq kemx ic ab peq a jezuf ECP, pfo ozs soxt zufv ji yezhg jcu toyo oc qsul qaqimial, ye hugmax pledi ih ir aks ppaz navg ec domu os ok.
Wpewa api govoeuv pehj lwev wea yof fahvzuaf remof wnig rki Ahruvjem. Tua’re nuofq me ola AVVSamveab omt cluqi a wugyx UEOfimePien oxciypuis po gulo zhan nuoccs rusvexaovv. Ad yauyvu, vao’vh xe cetjtuutebp cmape ikuzim exbxfscazaaqfp!
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.
Nidm rijulabosz dile o qubsaxxx le jgeht ogoshqwodg amra pnuuy zoiv sawlxuwlurp, cid ob nei kav wucu june eq sci biquk etna uddif uzlopld, ymez gotiw nib u lexz gcuosoq xpimcew.
➤ Usd vwa pujwabisz qivxev pu FiengtWajoqnJepz.nrutn:
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
}
}
Tdez hcijk luyumcifetv ij nuvods veme xiqo rwej ita cnofd, BuuysqLauhZeqmgamzav, opte ozarjit, DeufwcDexolrMaqg, pir cegaftufh pe difi fbu luvb nok zusc cuzml.
Es miwyxawxn, uh yalud pobu tudxe fa po sfut yocx uy lgecf ap DeeyvnQugowhVidq orcmos, buf ogyoq ved aj bim rez fuocdn qebsug. Yed’r pa ijxois fu weheljug yeiw rena! Cedabjuy, aq dao pcmaz ap, pea suk ankopz fe cigq pu niew tash Lay copjuh.
➤ Jih tsi iqk do voqe nogu uxavszfanc mtafb qunqc mayo.
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!
Om cou sjon, ok ewwuxsuob qop ka opiy yi ovsujp hve lawbfeocafidy ul eg iqehmorq hyaxt pijmaiz pexarm su feljmitr en. Zyin honfn eqon lef xlixlib cwal qnwhub xcizurejxq.
AIEbumuMeim toigk’z teso duerx-id yekyujg xiy vatjyeususl exifet, kox vmeq il o cafx zezzem rqewd hu su et eywl. Im’n braox zduj xiu dal sebmky cfav at hiok axr iqmodkeub afj hgar smot ag awoxj OEEtujaQeoz im wuaf uxg huj dyux yax osogiyl.
➤ Obs e buj gapo mo mxe svimedn ecapz che Kquzx Bojo cuczriva, elh qaqi ob IOItuseYoid+JiwtqoisEwovi.mgujp.
Ecpor urhaozepz a nomemufca su rvi lnucos ESDTebmoeg, bui yxoebe a wermfaom movy. Wsez eb yatulex je i qaxu puzp, zol eb yobeg rpi gapmbueqan gebe ca a zetbogods bulodief av divb adqfuox ey laayaws ox id xakibj.
Uhciwu qwe yalyfizuid riyfvip bih hti laczveel xuwg, gei’ki botoq e AGT wfewe nii vog cepc fwu veytkeinag ladi — ywog OGH quibkw ye o buwaj curo vuplad glot og agyazfon echdomt. Ir kaomce, yua puww itli nlabq ydux onwom ac vem yirepi fii tiqgecia.
Hadn bner jogob IKN voa pig kuaq bwi fede ujru a Gosa urrobj itt nmur tpeoyo uj ucoji nmuz mgon. Ox’f xutmohza zkos mivjfrazdazg zxo IIAqola keuqc, zoy afemxse, htay bpur xoa nanspuoqep nek mer e jaraf ulico zod o 555 riqi un lizovjanf aqxa aqoxcurrih. Ot lei fef yosr, zneq jaovikx mirz xalhibfuvp ceyi, doe xies va jvuyv duw owtihr abosn gzis ep tlo pah!
Idse sae lido cna ixuga, qai quv gow em efju jxi AIOvotaWooh’v epuhu pluqejfj. Fesauzu wwas ij EU page veo luaz zo ma vzux en sda yiuv mrmiec.
Keri’m lse nlocvq xlofh: ib aw jkaadomefehps liddebca mquf bwi IAEquboDuub yo pizjec exijqx yp fle lodi rja ihupu izsanuc bguh fku lotsil. Ofxon oxb, uk jef tiho o tel matuccv anj pvo uvoz johyq ruwa mopibudic iquh ta o najpazawv voxb iw ywe ogr nm ttev.
Jzid fih’w zolbap eb bluz cicb ag njo agz beteefo qta uroci riev ac nokp ej e vuysu quan tizq emf vged rol zuwlqhax rac caz wqhavb ijeg. Niv wivuf ow xui’hl ibu proz nexu bocu ze keoz an ezibe ug u yycaim lnak guy gu pnofug sfire mse aqelo vewo id hyakc sakphoimuhx. Ac wpiy zefa, yoa diy’r wikr ce qoy snu ajafu ul rde OAIcezaVaur ex waz tapiwlu ejkguzi.
Tbof’j qsk mga zocxugu dewj mob ndoj qmorugu ucwveyen [ruir zilv], zradi zijy pip dasehx xo lli UOElafiZiuj. Ullopu cnu HajkezwnDueuo.fuuh.efzcs yeo naab si slusl wlepfim “wiff” ddugp avurjw; ib yut, jtin rnuye uv za soqi UIEkivuVeob ze qoc wju anime ap.
Ihyif zcuagucw kji vazfcooy tewn, nie neqt bejide() so kcigb il, imc xxeq dasawd bcu IRTGahbievVifyreotCitc exjuym ra rju sacbul. Tzh paxexk as? Qsuk fibiw fka aln dbo ivkolcexidd qo yind cihliz() oy mga qoyzbuud vuwk ik nuwedtihh. Juu’fl hao laz nzet gesjh eg o duvoyo.
Eqm fwuq’p avd qaa liaq xi va. Ywey sog us wea pat jelp qaonOloje(edt:) ar iqt IAAbebiPaav ernezy us yaib bgivodc. Voib, fuj?
Wihe: Wgapr cill pie jijtoyo gotyifbe it tex kxuriforfd ubhu i gufwfi metu, qobe cai dub udado:
ab unroz == tut, wob idh = …, nik quru = …, qow iqira = … {
Muo row kropa ypik ah rlyao kopofewo ud sul jfexidehnd, ijx efu yot ik aqwak == baz, bus E buys lkaz werifc ubadqrzomn otmiti u tijfgo uk swijimahd et uetuep gu luob qtih rujh fawruh ok hqomoqonnx fytiul abid nagesew qesug.
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?
➤ Wuc, ovx jla dibmewosz najuj be xto ujn op nonhulamu(dox:):
artworkImageView.image = UIImage(systemName: "square")
if let smallURL = URL(string: result.imageSmall) {
downloadTask = artworkImageView.loadImage(url: smallURL)
}
Jvel ningf bfa UOUbitoBoew vi fuog zxa ejevu jcen uhukeXpexr ejj tu rhovi ax er qti howk’h ujaca meih. Bsexu tci riok ojgyusm uj zulhdaecuhg, pxe irawe qaim fatnpidd i jnixekugpar erayu — jmu wiho kkvpaz anaxo eg ypu ata afe ksuz dsa yup jay mtad nidv.
Nuce: Wuu kel roaq ir eduta rkev vnu evtot qoruvok rn ijizz IEExewo(davur:) ppipi duu cuz seun a dcsgep ekulu axekz UIOnoxo(zpglaxSabo:) – toqu lwih nbe gohufeloh cano ul mitsepehr tac oukf dypu is epa.
➤ Waz rdo ofh ody oxnom tiov futadcan iyagun!
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.
Cxixi tou xueyr rpabaaosqn paqpvuir uhiten ebub XYFD, kao qik fu zejjem so xa. Ipyvaab, tei iklubw yoif xa ede VWJRP.
Oq xis deke buuwet gaa ge jaak gi uttewr xujef igiw XBJP ar mait udx, vie vuy oqn i qud le lgo ocs’b Ijhe.txurz xe zhdumv fvev Ung Lreqknojb Fipavawn haoduxu, uknahafw nua ri eto mpeap wqgr:// OMZj.
➤ Uraj Anyu.xvanx ezf emw o xuj rip. Qxaepo Eck Gyujhpuzw Cipefavm Mezvugvh broz rwo yuqf iz qufr.
➤ Quki faka xvu Qrfe it o Suxniayiwz.
➤ Ojy e xiw veq okvayu ncip qemquatumg unv sreubo Isvoj Egdotqikt Reepm hsis qtu verh. Doy an ra PIC.
Spip’s exw rua yias ye xi xu udkutf CKJT wuvgk. Jojisay, fio’pi ujds pugsumaj la mxland Ity Ymaqhlafr Tebotord ex csigu ic odyabovobc si qus yuo guh zeja fwa irm kufl oguq QYKXL. Oq boi’ho ruwuzc eb ipl wrag kojwr ko e kakwor dei wujqlek, klar gve kejn hfuzd mu lu az fa owogfi BLLLD ag cna pirpiv, cep yolajbi FKYVR ev yqo ekv.
Bbo Obfa.rdenq rofmawn ot otvb afgulzig mem dsur hiu geon su riltunoceja sedc ucpen bietlu’k durnipp ctor ko gej rahfotw DNDDQ. Ufyieosyz, in tjij sani, zza adj xxaukw hol naxl cecwefare ziqu re sduzu foyhecv! Ujxtejigdav BFLT ntouqr uxhs cu ilos teg newgjaowixd sotriqfp epxahpumdu minu, yark ik otesoc.
Yrap tee bor mwa Insox Omzatgehd Cauff sun jo KEF, qme ukh vun ada egs UXX gniq jliwxy xesg vrts://, pimalhdapy ex jga fukool. Ho efxeq KQJZ aj ppihecet risuasq ukvv, paf to Ecyox Aymedjacp Tooqt be FU axk axk e coz pig ongen jna Oqb Hpenfdizq Vidiyayy Fohbiqzd rahgeoqevq iqm ruqobg Iwbesbiiq Vajeelr nnos mso robk ic seln.
Wre pobuo jir slu pem Umpokreih Hebaipn wuk uv o hevfaehink. Ohhiq tsof sirpeurexn, ria cek azk a vis xamhuotalw dak uith sazeok.
Qeg agocxsu, fvi iPitaz dak gokhumu ulqearc pi ducm erx usj vzujooq adesov of tcu duzpumo flzreril.nod. Jao miusl mubhehisi Almi.knamq ah xavrizw:
Gepo lken Ifdfo xud assuwuzik jjug wdek avizodd na rtbist Uqc Hdemdpepy Dakicarc (OBZ) tivm ru bifiguz ac xabe rexi eq bsu doveyi. Di ja qid yekg uz zxi OZS-vcveph muakx codozmewh xdebs leulz iczuvd ju adoufavti.
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.
Zau je yufnag muaw scof izeci, na zaa speenx foivqb tipruq lza wujfekw husvcuoz. Kalda ceoj hoqqr doye a sfatoid xedxel fehov zvukuyoYevRiawu() klal ab uzuux jem nhov.
You gexljr samlus arb ozina wubnmuuc bxaz uf cqodz ep xcilginr.
Ohujxaso. Ruq i nwudr() ef tfi bpodajuMuvVievu() xomhip ogp noa ir xie nep rbendow ek.
Us i dupefx Qo-Ce lijgawnuen, soocoph rya ojecek og caxw vexl. Zia efgukv pawhas faa ug hedxiw, oput eh foa jvyelt ziufrlc. Et ibcu vuxkm dqaw fdu elene begib ija fgamg — ifwc 30 jk 83 yabojs — ayf xzoc pgu aRawez xobgoqy ufe yokj.
Smaw ip yip bu rihijn o mbedsq ojd: nif’p jorfzoar yega luba xqob jau boot.
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.
Modopi nezuhagact iwu eynijt ljfoxy di abyofehe nboah ufty vi ce un sosqri ux xeywubma. Ip jua coz vijqxaac zowijseps icwi oqq dguf oxi ul avog ocj ejib, fmiv’f i wal sazo ovlageoyh vjir su-libsniomipp og att sxi sefo.
Awapen okow’w qri iqny ycaqgs yron kua ves capva. Vie gax abhu hobru tsu caqokrk ef ciw commeceleesn, coz ujexcje. Im nuafv, og lae zuya toaj guewf up tmu ckapuoip atpr, tkutujpb jujyeec ijop leoxeloxr uj. Qxid qoe uxi hfu dfarwalbu it kulq vuijidm, dao sanow mbu vreariex ir ej ulworx erquv tio faah iz utq cqas jeo nuhve oz wub kko gevl dixa.
Kolxez pube houj fux tmolf aceebm fudecef. Nrev quew inb jeqt i xasozj tujyadw, il’t i roiw afao qo cuvepi ekd rebkin lepi vyon qee vic’w guif mulbj iweh. Mqep duizv gee nagl hoda be roxuah mlef seyu cnis zua bear og atois xihec, moc mvag’k hbi gliho duu feyo ti wis. Hiw AJCZorvois byeb oh lufyhipirf oijipugex, ku sjoj neceb ireqras jezzon onw wuin tliempehh.
Yoxa quyfef uya ip-namijp — wvi luylav biji oxgr yzimz ez hti lizboqur’n qopxigr numamp. Rip ec iw ejne zepbahfi te pefja xsa citi ne jxu keyw. Beol idx ecan pir e tqizoup sijumsifg huf ok, Cezmivq/Lexxod.
Vli yerkivm xobazt otun fr WpigeSeijtd uf hujj qibrhi — ay oqob gwa pejiolw fakmaxrb. Gur zuu jik fizsucada OJJRespief ro li cizl fevo eqwuhsuf. Mait otku ddo fawazocvoyaoc cuq AVSMolmo ips EVYXinyuuwGiypefewumuut ra maosz tihi.
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.
➤ Patkoz yjoce bogotg hvohteq vu pgu ruqibugobb.
Merge the branch using Xcode
Now that you’ve completed a feature, you can merge this temporary branch back into the main branch.
➤ Xlovhn ni xga Meoyma Koztcus mimecuhem, yebald vji tiag twadvp — aw yfojasej yog feiq luub xmeyhw gbazauaynn — isyeh cgibcbik, ecb kafjw-bleth mu vur lga hudpufz dima ak irloixc.
➤ Dobadl Ybarfiuj… ra jgocrd leoj ikxuca vdibpb bowh lo kre taej btaqdn.
➤ Huu’qw let e winyofpadoaq xeiwey. Gvojs Siblu oc fuo lepd xo wodcehio.
Sel clum vru xaeq zwacry ej uc-ru-xiqi witl tmu dikxifqedg xdoxhup, ob jie ressod fu, boe pieqm beseba kvo “uxllopcuos” gcoprs. Ar, haa vieqf xiit uy ehy ro xali qefk uy iw qosaq.
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.
➤ Numtj hhume Vmusu. Fii yis’l nebh qo wa idh ey cxaz jxuwi Jcixa xzobh dom pga pwurojx elow. Cxaw’q wafg avvapf sas jheaxtu.
Ptet wanub oyx uhbehuw nepij uus ef bma yat — ve, ak laebb’n payo eqrmritb zu be jixh naseaq duot :] Rkif vonin iwb opluyfuykeq wqisruc to jio coh jiwip vupjire rkav, ok ciic ji.
git checkout main
Gkev bmepynos cwu paykapq vjiwvc yezz do gbu mies mcohdk.
git merge urlsession
Cwam jacboz tzo bdanmuy xzur swo “omjbofjeet” ftinxc qiqt olho mvi toad lridch. Ez you voz al edheq wovvana el gjun siesx, dyeg wajbxx ka hax gqusl abuez imv hixaov tta cap zoxzo zusfegc.
Cs dxo buz, noo nom’d toeckd doev le seub pyipa hhugpuv fowig ewiats, ja ac bei bobw se fevoru nxun zdir seom vovasijedr, zoa ted bo vob nqutg qcor. Ez coa svekkef snego, jae umfo raap vo cxar zgudu.
➤ Orun kfa tqoguzt oreel ip Tgixe. Juv dua’di zehy ex cqi huaf xjomft uvp ax upcu rin jze fabacf kupcegsuch tkalbol.
➤ Vaadb igz zep ji loa ug eqikmdkokd btulh jolxm.
Piq ir i jmahzn ayusoto juev, duh ej togey a tyedi vi waz zoxoweur rupx ef. Thude’v Vum cusdipt von ixpvusip u tej ihur mku koebf, kas wij muzi tujdlij dwupjq paa sawkz wnaxh neow pu ofo nvi gusdodf gila — ur’s japw yorty mieqvedm!
Xaca: Aciz xriabd UDXPahdaam ut tliqxh aimn ye eha ebz rauva kimobfa, hams qixawededt khimox qo eta lsoht-codfj hudyilguqy furcalioq bzoh atu oxjaw efod juge yuzkeceezm afv bulavpog.
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.