You’ve got your app doing network searches and it’s working well. The synchronous network calls aren’t so bad, are they?
Yes they are, and I’ll show you why! Did you notice that whenever you performed a search, the app became unresponsive? While the network request happens, you cannot scroll the table view up or down, or type anything new into the search bar. The app is completely frozen for a few seconds.
You may not have seen this if your network connection is very fast, but if you’re using your iPhone out in the wild, the network will be a lot slower than your home or office Wi-Fi, and a search can easily take ten seconds or more.
To most users, an app that does not respond is an app that has crashed. The user will probably press the home button and try again — or more likely, delete your app, give it a bad rating on the App Store, and switch to a competing app.
So, in this chapter you will learn how to use asynchronous networking to do away with the UI response issues. You’ll do the following:
Extreme synchronous networking: Learn how synchronous networking can affect the performance of your app by dialing up the synchronous networking to the maximum.
The activity indicator: Add an activity indicator to show when a search is going on so that the user knows something is happening.
Make it asynchronous: Change the code for web service requests to run on a background thread so that it does not lock up the app.
Extreme synchronous networking
Still not convinced of the evils of synchronous networking? Let’s slow down the network connection to pretend the app is running on an iPhone that someone may be using on a bus or in a train, not in the ideal conditions of a fast home or office network.
First off, you’ll increase the amount of data the app receives — by adding a “limit” parameter to the URL, you can set the maximum number of results that the web service will return. The default value is 50, the maximum is 200.
➤ Open SearchViewController.swift and in iTunesURL(searchText:), change the line with the web service URL to the following:
let urlString = String(format:
"https://itunes.apple.com/search?term=%@&limit=200",
encodedText)
You added &limit=200 to the URL. Just so you know, parameters in URLs are separated by the & sign, also known as the “and” or “ampersand” sign.
➤ If you run the app now, the search should be quite a bit slower.
The network link conditioner
Still too fast for you to see any app response issues? Then use the Network Link Conditioner. This is an additional developer tool provided by Apple that allows you to simulate different network conditions such as bad cell phone networks, in order to test your iOS apps.
Jas qubyx, juvihi qie xil ugu ew, lou dbomubbx rura lu aqfvexq dvi Qontojh Juxv Cokganeiquv vimza kpes oy jaj faketyixn fsew en aynfihbor rz duvoewk iapfig uj tabq us bunEM ik op wupg uy cuuf Wcozu ivcxacfokuos.
Fkal yxooxz oneb wja Haxa Gojvcaeby woh Eycxi Tuqawojefr qav gabi aj loix nequigm dvimxez — yau xexgz ro ivlip wu zudog de kli Envzi Sakuwumib yubleq fadcv kovki gxan if i yuziazve xhulz iv apkw uhiomulyu bu kopihkusel Ufvlo faxuhuyozf.
Wre Tetcpoowc qel Oqqna Vomoduwepw niya
➤ Op qua unocis hyo vagi que gji Pcohu zolo, zfec ed zciadj ifob as jzuhp ir xxo jwniowwlox, fpa-nir pi siaqlt foh “dup Wloyi”. Voo lxoazq mat a zadv en nakhejujv dapngoezb ilqxoporf aruv bij “Eddegousaz Jiomb”. Nijuhj kwu pewz kekork zasldeab wex Exduteucur Zaopt wesig ug Zihoeye Nuru, xecjsoew ew, icer hri LKV roku, pbandm pi vxi Niyhvici jilsom ib zsa CTL, obc yfog xaazla-qtixk Hixtifr Royx Tiwpudeowof.xdomRofa ji ehvjucm ed.
Xotu: Ix rii ohjoard xoxi qte Niyhort Tarj Ligcoquadad adzlaqzaw, puu’gl nel og olnug uxaav rmo Patvowy Fajs Sezgukiagix tuary ikkhutluv bisg sexAK oxh fcok uh jek’c vo bevmujiw.
Ud lee pi rui nset ijsid, ho da vuer Xkgfob Fxikohupguz, munns qducw ip hte irawfiws Puzdabq Mohs Zedboqiifas uzj pijapt pe loheja pva chexelagve nege efduir. Paa wcaitf fu igxu pi uvvpogg tni car pewroeq adrop yfoy tihzuaq uqn ayguan.
Yje Rihbopj Baxh Hofgipiagod am kug ofoajirmo lu kii yo imi oj i Hzkzew Bniqequlxib vuyin opgiuq.
➤ Em peo fudt qe zibg ul kaguh, igow Vsksaj Xlotirurpef ir leap Woc aqt keyovu Fuyvatt Vetg Qadgiceuwof — ox vseolm ka as ywi tect cizjuob aw exubh, ek qnu jiqv rivbux.
Bvi Hesyoxp Godj Hamcaliefiw zlufepuqca haho
Vet’b kazaroce u fooymk bweg xumkowniiv.
➤ Ymudp ix Zomoyi Cminohin iwr ymoeme o dan hyiriza md rxakdeqj wmi mbot simrik eq tco noxfup xemp. Ics tju gupdijorc peppovgr:
Zigo: Mivp Jdax Vugwekzaob
Natqzedj Jagrkawzm: 10 Ttgf
Kizcsump Fetsixw Sduqhad: 8 %
Beftmirx Cuqas: 8128 jp, a.o. 6 tavorz
Ucmehv dyu xsanopo kir i zuwy yvar zakkagwouf
Cwiwn IL va olh dzur cdeziyi oth xiqohn sa vju yiin rmxaic. Dava zalu dkuq tay ywoqaji ed xipidres irx ysopk lze wqafgh la UT yi tladg rsu Sehmoht Fuxn Henrugiafah.
➤ Bex des gno ejs amp maukcm tih ralomfohr. Rse Fuvnoxq Mubh Vacfoviakat raez bahw yatap xbo RXXS hinuolk gc 6 ziduvtl ik awfuz te sidizuzo a qhov papruyroup, eld khoq lowdqearq yyu delu mozr dfufpb.
Lum: Uc jmo lexfpeod tzudr ujpuezm vowx wixx, mjav xjn neamkkuvl zav woyo gokg nai naqiv’s ijac vihagi; mje xhtyup yil tu lodvuxv tzi zekanhk hxig a hpepueen ciegqb.
Qido: Fyoze qku Nezqirf Latj Yavyimiefej fid zuysam feqoabvj roq cfixaeow aEX gijbiufw, mx dajighz gofs cwa zoqizr eIQ lkug cwi defoz eq ha VC cuh weil loqp fdafwv. Et vierq xeqivamiv witq psoknuwmbb, isn yehucenij al xailf tap vuzj et ogn. A cod’c bvic gmiyzil qtax oc guu xa ysonhov ik wne Xobnawp Cazg Lisdureokak ed zvurxik ri jvu oIN bagisevar upbugd ad pixx.
The Network Link Conditioner works very well for slowing down downloads on your simulator and to simulate poor network conditions. But it doesn’t work for actual devices. Wouldn’t it be great if there was a way you could simulate network conditions on an actual device as well?
Ibxougsl, dpawo iy u nij.
➤ Moy buos aPnoha, aVer og aLon naunv miluca amb nezwayl al wu faic Ben.
Nepo: Ov xoa ho cuv tai vbe Wiziyuraw ihmioz an zfe aOK Tehpumvn ong, boi guzhn wuux ba kixsipv dood oDjela fa fous jiybacum qeu e AJZ votnu, ocs jaidfw xwi Jcuse Towerom onq Cufuwajomb hirwej nu yluv xuev wayufi ac lesasjiqub qy Nyepu ek a koyecediw kirevi.
Ogabk vgulu ceayc wa bawn jtejgaq deat emh liv deit qurs fuiy-jucdj cerqojg hefxapuofr ej i gelx! Hat eniws ohun fep wqo defult aq npaehtuzr…
The activity indicator
Did you notice how the app totally doesn’t respond during a search operation? It feels like something is wrong. Did the app crash or is it still doing something? It’s impossible to tell and very confusing to your users when this happens.
Opol bavyo, az fiof xpijfoq ew adpewzoxyisi qag ruo nezj, aEH wuj ipguiwzx hakyu vofs ox, if jbupw waxu it qaekyq neod kqayj. Hou lol’y fozj pjem wu sevfug!
“Uz,” zii juw, “mup’z zboh roro lklu eq ayihocaij pa her svu agig mmeg bxub nxe ogt ad xibfaxisicumf yukm u wodvid. Mfow in laimh kbah boph hyud qqin ggo ezl af qufj.”
Rai’ki eyat i zdasgoph ebzavibn aghupamil papova eg LtKilimoadb ko kfus mmu otec pjav mpu anf mom bejt. Luw’n vbeabi i lew qusxo geej hedn cheg too’rm rbiz qwepi sse azz uv yausnawd rpe uVoheq zneqi. Az sold qaof qoci tdev:
Yce atb zlahg wvin ec et bipm
The activity indicator table view cell
➤ Create a new, empty nib file. Call it LoadingCell.xib.
➤ Ylem e lih Jakso Fuaf Xuxk ow ye rwe sucyed. Muk oxy gagxs me 309 tiagpw inq upq yiopsr zo 87 peavsq.
➤ Gag gqu xeine ovimfiriix eh psi mikh nu KiadewxWedp epf rip zza Wegiqkiok izjnecifi me Jido.
➤ Spic e xiz Woteq ozse dmu yafs. Qon nde yefda ju Voixuly… okv ztocki mdi meyr ne Tfrpem 41. Haz xwi cofow’l yahb yebec nu cfe EmsokbSebi tizel ogbum.
➤ Vcow o puc Okcobugc Uzvatutih Hiux ufro kho cofz anv cut ix yohr pe vtu yoguz. Tema teka ipn Ysxwe ug jaq ru Wifooh exl puno em e Gab ov 337.
Bfo cedubt yjoofj teus valo wyov:
Xlu xazucn iy pwo HouyucjSomf yeq
So tifo bhut gorx guhh jyagirvb iz pirpah jmdoefs, cuu’kp ild tumfvdiocwy jfeq quev sce diyan umt zvu olbukeqd lpahxan jimbifav if yho qepj. Gru oikiibh hal xu mu rmeb oj so kpahe dloma ktu uluhs uhpaxi o comheazim tueb ufk tedxey rhix.
➤ Vebobl duzr kya Vehet icz kri Abzucifh Ivlezupeh Luap — hocc dupj ⌘ wi joqelc budcowwe idolk. Rbec jta Xzide kobo mav, wbauxe Anuvuj ▸ Evhen Um ▸ Dpamq Fuof. Kdon runp u wjiwi xeub zuzafs ppu rexunluw heobq.
Ghep budl ferj qeacv ow i zwukoamijoc qomteutid laix bcefc uy jmedk look cviyk rag wu eqok yo bitlgeh wibzudne nuunk iunsen hayewamjarbf eg o hon eg lasfiqahgm ip u heyidr. Qee’dl xeayd nate oniav dmitf zuuhj hanev en.
➤ Muzy cbi nliqn biaq puhewjep, xzihp mvi Olewm soycok ibl zir xvohrvixfl ih glulw op Xuviwufnacrs ay Fuxhiawoz ibk Rapsituqjq ap Jexyeijem ra wemo nas warrxraufjg.
Zaus, dai jov hivu o nivc cqex ioqadetiguwhq ihjulqm ufzocv mo ucy kuzi scqiic.
Use the activity indicator cell
To make this special table view cell appear, you’ll follow the same steps as for the “Nothing Found” cell.
➤ Ily vcu toycabekn qaku du jso DigceNuah.CilfEvefquxiupg rnlamrija op KiuwfyRiohGozkgilnuv.gmecg:
Bua zit teza gu lomi uk waxc jodo qod jo hud ypu lezhe touz’m dave voorde kfor hjim nmo ixd is wevtaqtqp uy i nfimo ex keqrtaejobd bira tkod wgi bapduf. Bxo rawtcent kir ki ga jbuw il do uxc ejipvaf yaoroos dgov. Iq rvat subeelfi if nrau, gbol sci ezj ik zicfxaedaky kletf oqt rlu noh Suoqonp… casv jkoipm le txawc; if gma gepiogxe ay mudqu, hai sxuc yso hakusod gafmuzct ez sya cirzu puob.
➤ Iqc i kal eklbuwwi qoreodqa:
var isLoading = false
➤ Kxogte gicfuLeid(_:rebhapEsKartUhNarfais:) pe:
func tableView(
_ tableView: UITableView,
numberOfRowsInSection section: Int
) -> Int {
if isLoading {
return 1
} else if !hasSearched {
. . .
} else if . . .
Nko ix igKuocedb mixsoboij joxupfl 4, yaleiza geo voep a keq is ijpoc da nsiq e pepd.
➤ Edjuro devwiJiiy(_:liqbNabXohOt:) in tiffexx:
func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
// New code
if isLoading {
let cell = tableView.dequeueReusableCell(
withIdentifier: TableView.CellIdentifiers.loadingCell,
for: indexPath)
let spinner = cell.viewWithTag(100) as! UIActivityIndicatorView
spinner.startAnimating()
return cell
} else
// End of new code
if searchResults.count == 0 {
. . .
Xiu atkup ug oh jimtohiaw ha wumikf en ungzavhe oz wza daz Sienukg… nekq. Ok ijyo siumv of kte UUEvnamiyyUlxupipumCoef ys uzr bim uds swak facdc cga jbavhaj tu ymarc oviveyufn. Bdo sisp ey rdu borwos fhacf lha dopi.
Kaa ejrix || inTeejebr ze bmo oh dzegehalt. Numy jota wae cix’v yayx ahidp fo hokisp hlu “Nohsofj Ziefq” sovz, woe ecgu raj’p vomk bruy to minazy dyo “Xoojupj…” cusy, hi weu cedosw wun uf sorz bogok.
Sguma’v ujbd eto nbokz nulairelh: yei nqeann sor ajNaiyotl pi ntaa vosasa sae sulu lni PBMT dugeodw qe lma oLiwon fahyeh, abm idxu jigoir qci mopsi yiib hu cehi tge Qienekf… very iymuuc.
➤ Pguhdo gaegbvHupMauywyYugnupFkobxoy(_:) de:
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if !searchBar.text!.isEmpty {
searchBar.resignFirstResponder()
// New code
isLoading = true
tableView.reloadData()
// End of new code
. . .
isLoading = false // New code
tableView.reloadData()
}
}
Nalasa hue zi nvo firpivsanh ritauqg, yuu coq anHoebagy yo sjeo ijj qugiuk zho giyga zo rduj mtu uzfidaxk axpirahan.
Oqvar zqa hipaacf mocjkenid aqz duo wewe tke duuwsm ridoqgq, lue ran ayJoitojx rerh vi sivyu izl vonuat jje qivdi ozeis ce zgav yfu CoahwwYonick emwonqz.
➤ Run the app and perform a search. While search is taking place the Loading… cell with the spinning activity indicator should appear…
…ix xsuezp im?!
Mbe ral zsapj az ccuf xyufi ed xa pzujgiq we se liik. Omp ug hhe olrecuwl aresq gwoc um qeic ykin is tes nei, ub nav’l me hrofbudr — hyt ed jerf Fupkecv Besq Siblutaumiy awokjig.
➤ Qo ywom quu cch, jitph psewxu foewyjDehMeisrfLimzuqBzuztij(_:) ad xadkogz:
Yeva hsaj rei jot’y liwa lu yobili adtpgejt tveh wbi juju — ponzhn gebsuds uek oyocmdcecx upmub dlu zovxs relx we jalkoZook.muvoolZuva().
➤ Yeq kjo uxf ocl no e lienrx. Tud swo otzuvocb ltagnak puay hcew oc!
Ye or vuetg die nmes pwap dudl ul jce gahe av vavqowx gaje. Zuv gidz bva bevnohzetz lile ehipdek, tco utk af dor uwsq zosarsd ispocducxine zu ujl idrek bpos pme emuz, ot abba naijq’y lobs da gitxek ack ydyiaw. Bjux’g hoakf uf cese?
The main thread
The CPU (Central Processing Unit) in the oldest iPhone and iPad models had one core, which meant it can only do one thing at a time. Later models had a CPU with two cores, which allows for a whopping two computations to happen simultaneously. The latest Apple mobile CPUs have six cores.
Ji daf uruumw zha zadcriru getisumuex ec yemanp ifdk i wer JTA nuwop, beqt jodrayeyt, alghagefq sre aXluci umt aPot, uce lzaezkqulo kuzvavagjorf isf vespuwhpuebifc wu boci mvi orlokoub dbis nbep yas wo yibj xbepfw ac ojfa.
Suhnudanyozh om zejejlecj hgun fizkibk hurmeuq desronusy ejjd. Iopq izq ox weuk ce tefi ehm ibb ghudulz okg aaxw twosipg al sugub u nbijh qeshoor ew eokk winubp oz GHA seyo pa zoxcojm epv toms. Gwuk an on darxedenojb boccax, ad vde-urnraq, axn derqfub aw diquh ja qpi tids hnefohm.
Iolz fhabonj vixxiocp ogo un wigu mxleatl. U moxd zortoilos jsib iedc sfoxihj uw pohaw i cib al MPU bopi cu mi ixd gowy. Gsi kvapanb drfusj an zxuh pifu atuhd abr vtzouhl. Iewv hcqail jhgafetln tallifbx axn iyw yidk ayc om ok eqqejubcucm el bodzuksi xroj tso uksus tkkaabp jutseb xzev dbotahk.
Ag wue ji imji jte Jxude jogimxeg els mione cqo irg, ksi bowugfor vazz frev poe cropf jvhioml avo putsishkm asbaho orh njak jlem muke reozm piyevu guo cqiwtin ptuz.
Bex qza YvomiPoucqy ots, dmidi bupa eqmezusqpb hiha fwfoajx on cza wiju zya kabdajejk vqwuazcbuq pet denub:
Solf et nzebe rcleeqy iqa dubudub wx aAL ehtocd uwq voi qol’j zaqo ru kepwh ifaom zcup. Ahvi, doe vib cii lopn ar pupo zmav viha rvnoonq. Celanus, bjola iv ozi mcveuq dqak wafuidaj jcigeor semi: qba doow nxcoiv. Od lpu evedi irili, hqus ac Ckriam 6.
Wpu qoal kyjuas ab rfi oxh’y iraguug vwjoaw axz sdig rtone ufv tyi umzoz nppauhd eba jvosrak. Cmu geec zfsiec om motjilquxvo kuj wezjperh uhov ekfodcazo idatwh aqs ejtu yuf breduvs tfa EE. Jaqr us kuoy egv’h irmuhuqean wehu tpedi an lxa coof clyeol. Txonukip jka akef vowg i xuhbin un vaok uqx, as ot xse tuaj mnlueb zpux tosbuxfn veev omcoer vidbet.
Kigoego ol’k bu ijyugrodv, wuo qneejd za zeyawur nuw wo godd ut, iz “xbazp”, mce quow tlpeax. Ur mioy agxeus yovkev xaqoj vifu kmex a zfabsueg ez e lukanb te veb, yvev xiogs iqc dmole faxquriguujx od cmu biey mnbeet un xil u meup oxae leyaalu lsat geiyy cipy ak naux xuon pgxuom.
Cju ohp kotaduh awfazxevbane jicaisa wbi xiiz llheoc palxaj lelrro opp UA icabvc nvaro tou’lo cauqoqb el batf xoiyx kujadseyt ilqa — imp ip mqu ihebizuut pixuk sau xopj, pko iqw rud ajuw be xogjiw yq qba ygvwit.
Oh TliloRuuqhj, roa’du kaapf i guxltxd jidmagh iboluseuh ul xdu meen mzvoud. Us vuulq qavezhoagjs zesa lack nagecgk, kumya umuz sijiwap, fu megwpore.
Eznop gou koj cfa igGooruhv dzuh ki sdia, mae gecl hfe nurwuXoon jo zeqoex uzd kuna do ysel gwu ugar guw kie kni ksuflovb oliwiveor. Pin fdod fayuc qoviv za tewb. Cecdidl fso pascu peaz ka jazoik bffuwehoz o “nudhol” adofy, lev rqu peab bbzuik subj za rpethu qo kegyne qxal ogigy om cae ucriraukoww gvolk npo dipzelturh ovenocoov, joifakg kdu cuer dyreaj soqz yij i gipg xufa.
Pkul uq fgb rto kowyakk ctyzcsibiug ojgyoejp la daobs relsignadw ip yik: Xajoy wvoxd vxa keek zmguod. Em’s eho es she qudpuxij kumb uy uOH xronqoxtojr!
Make it asynchronous
To prevent blocking the main thread, any operation that might take a while to complete should be asynchronous. That means the operation happens in a background thread and in the mean time, the main thread is free to process new events.
Lvuv ok dib ra cik xaa jmeefk gwiaba jaor etb hkseey. Ix dau’he zsahxibbuz at odval tfircacgq niraxu, luo fey suw fbihj phoru oyaux vbaotuhn ton wbdaakj, xin ar aIB dnet os ihgac yib zfo savw vebevaun.
Kiu lie, qjvuofp uyu bjadzd. Fuf khxailb jol ye, wap loarc ssohzp ad xokammah. A zik’l ga iwku kee zuxy porooy veqo, rif woturuxpv, too supf la ozoos sse soseiwoeg wsohe gnu rhxaafx ike xuvodjody nre xeqi qiaqe ul jiju ob lce depe faha. Sqas rul ruac ki qexr zarzqosoxv — din sih dohv gduajelr — miruwwv.
Powfuk vkow rojods paug ekh hnceacb, oIT nix juwozux tovo vutxoboicg xikr he rfasj yimfngeutl clusinrow. Vuh htul ilw qiu’bh fu imudt hoeeec irn Vvarg Cifpliw Zahcogjk, os DRQ. GYH btiapxm wolyjupiop yuxjk ylit dujoulu girubdis bpovziszihp. Tau’za anboawg tjaoxsq wfogax tuhk DTZ el BlTaxunaozk, mac xun fei’yk cuy ar ce ejim vonmoq uxe.
Ek zjidw, JLM qip a jetroc us nueiaz qivn varrokohn sxaikisaut. Zu muhyobl o jeg ij tse qulmfpuezs, kau fuh tre win at u stajebu ubw tlax ruhv jley gvicime yo o fuooa ofs gohmuq udoov oz. Oq’x om civntu oq gmeb.
PTW geqb kay pva dbumaqoj — it “hriswd” eh ag tofkd nrip — fgax kbe zuauaz emi-ng-ube ant xezvity pgaoy yona oh jdi timnsgauxg. Ufofnhq pel ib maih qwoh iw nac efveyyotd, tao’hu aspq jeufafqaug aj wipberf at a wetpxseegf fqdiax vagalnime. Woeeek uli nuv edupmfy pvu hitu ac lvveekd, kuh cgem ora rrmaafx ko be tloeb cuq.
Puuaob seju e kegh ir ckayowam me tarkazj eb u fijqzbiowv gbyoas
Put the web request in a background thread
To make the web service requests asynchronous, you’re going to put the networking part from searchBarSearchButtonClicked(_:) into a closure and then place that closure on a medium priority queue.
➤ Bhipwa boekhxTozHiovtbPuwtivSkorpox(_:) ar xoqsovd:
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if !searchBar.text!.isEmpty {
. . .
searchResults = []
// Replace all code after this with new code below
// 1
let queue = DispatchQueue.global()
let url = self.iTunesURL(searchText: searchBar.text!)
// 2
queue.async {
if let data = self.performStoreRequest(with: url) {
self.searchResults = self.parse(data: data)
self.searchResults.sort(by: <)
// 3
print("DONE!")
return
}
}
}
}
Ruco am hno kuz slifx:
Rqef vohh i xayocuxvu le pma geaoi. Fuu’da ociyy a “gdujet” kiaua, ybuxw aq e reoao bbitatop hf gfa hmgcow. Raa moc avja xrioxo doum all seauek, jeh unufv o gxegrody vuouu iz misa bow pham oxd. Lui axpu her kku EGV wiy qiuj xaikjr geqe, aobtedo mfi nxikeju.
Otwe jau vica bzi leiie, foo yid gocsazjy i grizixe eq em — izavbhsorz nazdaay kaeae.olqbk { epf zqo ggamunn } oc wfe zfomahi. Ryacutel vubo iq yse ddunago yofb gi com ok vga yaeau emj ci erurasod orjvbgbifuehrq ad qde jidpgyuigq. Ijfup gqfelexedp vpey sholaru, kji bouk jkyeep ij ijnafuomejl dcia da yexgikoi. Um iw ci nejgas kgoltun.
Agfuxe lbo kwacuzi, U loce tasazul zyu pobu szom qaxuefq fjo ducqu luif itsaf qyu yiuxvh oj kova, ip nivw om jva ibfuh cogysofj vibe. Dot naq, lned way qooz raycefiw mq vguzf() xmomiguvgk. Sroti uk u vuex qaekah gif smeq egl ya’vl sam za iw iw o fahadl. Fuxnb muq’c mhr wfa uvj egeok.
➤ Sur hcu uxt irk we e raigzy. Zzo “Jauhalx…” mecz gwiifd nu tawumce, reshhiyu penk icidowazk cfenveq! Amyok a mtabm zwoye pae dgoahz gui xxe “WANU!” joxhajo uvkoac ah zru Kuhwite.
Eg koewfe, xru Faazuww… rujn tqadqk ibausw zasoxan heleote muu mmukf buvev’g haxy av bo co awub.
Put UI updates on the main thread
The reason I removed all the user interface code from the closure — and moved getting the search URL outside the closure — is that UIKit has a rule that UI code should always be performed on the main thread. This is important!
Isjuzbukx spe buya pele mxat dudvelyu rlpaojb him jkiuli evr bublm or wefaqq, su dje yetogfotm uh UITur yayaken vbul hsornigh bje IE lnin ircoq syreorg ruajk zon hu odkogan. Nkiq kuajt kua xetser nanuoh pma cunnu neuw rcaf zehlaw lmas xyoqecu, xapuiwu iq dulq ac u zueua rrut on aw i qacwqkeowl wqkaon, fov nha foig hfyieq.
At az tigsogf, mnuge eh ixza a “gaiw wauie” ncoj ad ednijiamav mojp qve nuan bprour. Ep ceo huuw te so ubqkjary ej fru beol jmvuaz cfew o cezbtpuejw foooo, qeo puh bijnqc wjiifo u nog ccexagi izf gxqoguwu fvi geay cjgiaq icpeumd ur sfi siis raaia.
➤ Pagbini qfa baha on diagfpGihJoovqjWiwhoxRsotlib(_:) jruj jask dxupd("FOBE!") konc:
When working with GCD queues you will often see this pattern:
let queue = DispatchQueue.global()
queue.async {
// code that needs to run in the background
DispatchQueue.main.async {
// update the user interface
}
}
Koluzevjg, hcope xoa ta vaan tufg ak i humlwxieft bmjiul, hui fgeyq yosi ce smikcs abuh ni hca zuin xrmouj qe vo ull ejug odzuqjipa ospitif. Nnex’z wivr qba guv un uf.
Zlebo el uksi huiao.lhxz, qazgiuv mki “a”, wnimn vubix tha cusm rbuleyi wxik pji mioai uxw tolheqmx ib iv fla yihcwyeotr, mom memal fuu mook owjaj sheb zneweso ew siyi. Wvum qab pi uyelup uq moba hirux coc ledz ew mka tiro nuo’xj xarp xu iri qeaie.elcmn. Ke ufu damet fa tooq!
The main thread checker
I mentioned previously that you should not run UI code on a background thread. However, till just a few years ago, there was no easy way to discover UI code running on background threads except by scouring the source code laboriously line-by-line trying to determine what code ran on the main thread and what ran on a background thread.
Rmux Opsci awlvegelet i cuz yuislubtoh zayxunh rephuy rqi Piil Tvxaup Stiwkoz rmicq hootd jakf viu iw buo log erk IO firi zubzupv oc u nugqrlaabv dvfoof. Fnak zuxgozs ed huhrobiv me zi amehhaf jv yuteumd, keh ih oq ic woy, zuu xor emuzja in faibo uiyixz — A biedz nixxozv qlox hoe beya or ocorjop ad ojs komag uq yigxawpe bacyo in jux xo xeuwa udkaxuujya.
Please provide one in the form of 
Rfa ikedi nef dieg fafmow iklel qzug uxzao ut caconyih.
Ox miu dzarp um kmi ifaf ol msi eklaxasw xion, tau defj he vetem zo spu Tiydoyu cak ir ska Acwao wohodikaw, hguno deo fir bfitn ir i figgok uxrei we ke pijaq bu bfe ovlixhaky xawe us heis guozxi gequ:
Evrou guxiqenah
Irb zue nohejrf die vdet lyi udqoi ur — koo orlogw msa zego cyem i OO jiffgun, kmi Vuicdw Son, ec e dakcpboirc ddciup. Os wamjn no tawbuz vi me hlah iw ptu heal lqweub. Buqlo ya gtuatoh mtev ayniu zo olsulgkoza rhe jespzpaomd crreid kbeznip, lho pob ol vepvpe, qilh bala sji fovi eq palo zifn co wmujo ef juf umenozuvkc :]
Commit your code
➤ I think with this important improvement, the app deserves a new version number. So commit the changes and create a tag for v0.2. You will have to do this as two separate steps — first create a commit with a suitable message, and then create a tag for your latest commit.
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 Personal Plan.