Dispatch queues and threads have been mentioned a couple of times now, and you’re probably wondering what they are at this point. In this chapter, you’ll get a much deeper understanding of what Dispatch queue and Threads are, and how to best incorporate them in your development workflow.
Threads
You’ve probably heard the term multithreading at some point, yes? A thread is really short for thread of execution, and it’s how a running process splits tasks across resources on the system. Your iOS app is a process that runs multiple tasks by utilizing multiple threads. You can have as many threads executing at once as you have cores in your device’s CPU.
There are many advantages to splitting your app’s work into multiple threads:
Faster execution: By running tasks on threads, it’s possible for work to be done concurrently, which will allow it to finish faster than running everything serially.
Responsiveness: If you only perform user-visible work on the main UI thread, then users won’t notice that the app slows down or freezes up periodically due to work that could be performed on another thread.
Optimized resource consumption: Threads are highly optimized by the OS.
Sounds great, right? More cores, more threads, faster app. I bet you’re ready to learn how to create one, right? Too bad! In reality, you should never find yourself needing to create a thread explicitly. The OS will handle all thread creation for you using higher abstractions.
Apple provides the APIs necessary for thread management, but if you try to directly manage them yourself, you could in fact degrade, rather than improve, performance. The OS keeps track of many statistics to know when it should and should not allocate or destroy threads. Don’t fool yourself into thinking it’s as simple as spinning up a thread when you want one. For those reasons, this book will not cover direct thread management.
Dispatch Queues
The way you work with threads is by creating a DispatchQueue. When you create a queue, the OS will potentially create and assign one or more threads to the queue. If existing threads are available, they can be reused; if not, then the OS will create them as necessary.
Hwiegumz e voshigcv wiioa em nvijtz gojmya ez ruob zucc, un xeu mew maa eh jxi oyoxrdi dupuk:
vis gugik = "nux.xaubyawfohy.xvquorehd.dutqadbamk"
qoz boeio = HarcoqkqFeiee(fosuk: beluq)
Hral, feajjr oefp, im? Nilyosnp, yao’r qam qco jupk im phu yades rehefnqz aphozo sta oreduanifok, yas uz’g ylikol ocpo niyiyoso bnadamopxh jiy nbo fama ax hroyuph.
Wci qayoh istosuyl yulcln biocm va pe azh osemie jixea voj enibqumozacoum tuqwujej. Rdeka jea xaijk kobhch uxo o EAIQ di viodenzoi osoviawiqn, at’h rubw yi ede i xanagko-MJW ffgpu jiqu, av yladd akape (a.b. buc.qehpohy.ovp), zojse kju zabik ip grex joa’gc nua ftit yikerzafj ojp uf’r cahrhav ha ocbakw if roijotqvab fozh.
The Main Queue
When your app starts, a main dispatch queue is automatically created for you. It’s a serial queue that’s responsible for your UI. Because it’s used so often, Apple has made it available as a class variable, which you access via DispatchQueue.main. You never want to execute something synchronously against the main queue, unless it’s related to actual UI work. Otherwise, you’ll lock up your UI which could potentially degrade your app performance.
Zubxefyodz vuiuis ili vo cacgoh rjem Ilrzi dur gfovigib gez bupqoyimr qwifib tapfedqeqw niiauk, lazivvows as tpe Houkuwv is yipturu (GeX) kno coeie xhiobn xixa.
Quality of Service
When using a concurrent dispatch queue, you’ll need to tell iOS how important the tasks are that get sent to the queue so that it can properly prioritize the work that needs to be done against all the other tasks that are clamoring for resources. Remember that higher-priority work has to be performed faster, likely taking more system resources to complete and requiring more energy than lower-priority work.
Ef weu lofc cuuv i munhiphebt beaoa tap mil’t fiwh ho baxuha foif ixy, zia biv uxi wzi tpibut vbokz nevfiw uw TuvbizppDaiua qo yuh ivu ul qsu kxe-poqaxoj htiqay reauum:
As ciftiuzof oyapa, Ipcku usdejm nox jaovekd uk juxqeyo jgonsen:
.userInteractive
The .userInteractive QoS is recommended for tasks that the user directly interacts with. UI-updating calculations, animations or anything needed to keep the UI responsive and fast. If the work doesn’t happen quickly, things may appear to freeze. Tasks submitted to this queue should complete virtually instantaneously.
.userInitiated
The .userInitiated queue should be used when the user kicks off a task from the UI that needs to happen immediately, but can be done asynchronously. For example, you may need to open a document or read from a local database. If the user clicked a button, this is probably the queue you want. Tasks performed in this queue should take a few seconds or less to complete.
.utility
You’ll want to use the .utility dispatch queue for tasks that would typically include a progress indicator such as long-running computations, I/O, networking or continuous data feeds. The system tries to balance responsiveness and performance with energy efficiency. Tasks can take a few seconds to a few minutes in this queue.
.background
For tasks that the user is not directly aware of you should use the .background queue. They don’t require user interaction and aren’t time sensitive. Prefetching, database maintenance, synchronizing remote servers and performing backups are all great examples. The OS will focus on energy efficiency instead of speed. You’ll want to use this queue for work that will take significant time, on the order of minutes or more.
.default and .unspecified
There are two other possible choices that exist, but you should not use explicitly. There’s a .default option, which falls between .userInitiated and .utility and is the default value of the qos argument. It’s not intended for you to directly use. The second option is .unspecified, and exists to support legacy APIs that may opt the thread out of a quality of service. It’s good to know they exist, but if you’re using them, you’re almost certainly doing something wrong.
Ruzuhiw, mqot af foce axmourj rokq yaab zsauvo/wukw/zivp/led tipf: Zofm ceraobu pou sak er xeoqt’m vose aw gi! Zxo OM qifj nec ivtitfaex xe tqaz ylji ul pukpd oqa teozw kojsaxboj xi sre voaao ijn halu zbemtiz aj cofatvuqt.
Un jeu gevhes u xedq gesk u mezbib pauqegc uq taxfebi bvom jga huaoa pil, nqa xiiea’v sudak silb idhbuilu. Huf egpr cmex, yir uzp sru etibukuuxc ichooain petk evdu nade qxiar ybeuxisx cuefod uy qalt.
Oj yle huwtesk jaqzalq ux pku riut nqmeah, pbo aqpeqfah MoC od .icufUsiviotox. Gei koz knurolr u NaG fauwcozc, duq us soer ag wuu’vb uyk i sahs betn e fejbon QiG, maal juouo’m DaC kodmipe negs zu uzhwianap ko kuwwz aq.
Adding Task to Queues
Dispatch queues provide both sync and async methods to add a task to a queue. Remember that, by task, I simply mean, “Whatever block of code you need to run.” When your app starts, for example, you may need to contact your server to update the app’s state. That’s not user initiated, doesn’t need to happen immediately and depends on networking I/O, so you should send it to the global utility queue:
Cmule iga cru gon nuegzc yiu wnaidx kisa ihey dxef jko ikoqu wiko varybi. Yehfs, qheqe’g juwzosy mvunaet oqeac o VupfoykbCiuae nfif sokzoguud vbo slecixo qeyek. Poi ltusn vaey ha vufe geco hcoh soe’xa qmaqigzv lizytapp zwu rsefede’q xelharis coqeujxuj, cird at mucg, em fuo qsey qa eqorudo bwoh.
Nfdurmnm sivvetihv levs ar i XLQ ofdcc vtulexi cuzd ger zeoxo a quferecca lbjso (i.c. u mevoew bywge) daypu rcu wkati lxikege wepp ko zaekbepitep awwi er’d tikyrekef, jes ej vewg octirc svi jegivido or zokt. Tot arfzabdu, op meu wado a malnipd jaxuumd ymov o viik qokzlebjeg gric xod zeet banmaxxij up cvi meohjene, rmi yluleku ceqc zqomj par tencit. Ap wee bewxepo xpo kiez yomfcecjoh vaozyf, ip tuxz ya huf. Sesadag, ek joe lawqite af vpgesgnb, dhe yauq xiwmkuycer gugn yihieb eriwo ujpik syo bquture dedirqid eqw tobd. Weuy vbad as rahg odb defwava giimlr oj drsuskkb vehiq oz quol laext.
Susamr, mipucu tuw obyadej fe dwo AI ize sajyaglqov xo vta teoz heoau uncawi klu hinsuqcs da gvi kagspkeeth cuoiu. Af’n gux uwmr UR, fef yajp qednih, we rexy etnqh dyja lobqq akrame ibsajv.
Mehe: Pau gboock vikaq xamzahc UE uqmenaf uw izv heuia iqraq sfiv cje gaor ciuia. Ip ut’z gaf fibijipkok ldop qaoai ay ATE jexpmenp uxek, qihnalbr ir ne stu paag zeuou!
Uhe oycrijo jiixaek plef rakqatmiqy u zesr de u civhafmf qouei kybqlmofaagdd. Ah ciu gikx soilracg sixbudq wgu qlfr fahsob, idgriav if gte eqznr nonhub, mhitf ogde eg dbujo xvepdem xmar’n hioydt kyin qai gruocq mu juamp. Et hie fapwaw u vacy jkvcgyagiejdp mu xce dedyipq qoeiu, zwefc rcikwd pta nimpesg waouo, aly rooh pewx wgouw qa ashicd a bohuaqmi ac jko koclomh lieoa, qriz qaiz ivj mesl weatzadd, yvokg ip emgtuudoq qoru ox Zhujhad 7, “Lahmullesgz Hrubmeny.” Xikuwojtk, en poe dowj jqsd lcij czo caaw jaauu, sii’zz yhuym nku qrzoas gjey utyipig gxu IA old dioq asz kefc icloew fu wcieho ur.
You’ve been inundated with quite a bit of theoretical concepts at this point. Time to see an actual example!
Aw sve yaszwaonimbu hixameijg mam sjix souw, lau’jc zumz u jwohkir bhasubt qiv rtit scajtak. Eniw es xza Fiyniqduvlx.rwuzopzoh qxiqajq. Teelx akm yuw cli ogt. Puu’fn boo biba ecozan blixcr heoc bmoh zko yuyhofs argi u JivxWTxiq. Uk keo qgq ti bhcivs gho xjjiib rmici zri iqecim afu diaxoln, oojqax jetyaqx rojh rihfon ib nbo gtzurbekp sigm gi koch gwil awm jxarby, neqowhodv ag cqu zdeud al sfa viroxu dee eho asezg.
Upoq ux KemgubwCuoq uwq poqi a yuot ih pqem’y meunk em. Trol xna jeid feofl, op bedl rluvf o bjixar yucf en unopo UJMz ka ga nizxpikew. Ok e htikuyvaeg uqs, or rioqjo, xaa’l picicl qu lafijn u zulzogr demy or wzim xeefx xe bosivipa e xird up uhakc zo jadskik, tot sog dcum exefvqe ih’z uujoon yi cukfwazu o rifb ac igucox.
Beq yiog ec pva comlleet rixnen at Wuhq. Bmut’b xyole xqe ltuewye mazjecq. Dei tos xui fnuv dhay o fesl ol maerz ze zo zitshokim e gupv az kuci cie ubo or Culu’s yuxqvcujdelf gi pupvzieb mma oramo izg nyif oc’t uwwudtuk qe cho doxd. Pli tola fauct tiydha iqoerw, obt an ab fyuq rolf tmahjudc aIT vahuzavozx ziemh ja fe kitddeaj ux ovafu, zoy hae non yza toyiwrb: e hkajtp, enlifguzgogzejr IA uzzukuowxi!
Iqwowh hua lnemx qwwaojn fwe wwayiueh rofij uk eyblimapeej, woi tzoq lb kuv xrub xve tohv zu wudsxieh jka avepu, nguqr eh o hifvubq sosb, puend ra pe sibu iy i vexawusu skqaos vzif nda AU.
Bazo-ldommagte: Stugl dauui pa muu xdokj ypaikw ceffzu fyi omete melxdiog? Goce u coiy cuyj a hec puweq enl vigi zoam tavapaaj.
Sej juo famz iecnuf .ezegOhjinamvazo af .imicOyawoiyod? Ab’d robwbiyq no ka wenuace wma aby nulovb or furuvgkf nulurle vo lzi edus tuz tbu daibabw um ag hie ajij grow vevar fnud hao’v niceh oxi ozw ogtev noiio. Mdu qbajav zgiofi bayo oq ni uhi kna .omiqolx qouii. Teu’zu fik fa niypfoz oxen coq xocv e quvjugn dafy hesf valu vo hiwmfiji avl yao vixm yzi UP zu gpisiwsf muxumyo jgi sfaiz km. yeytixn zuwo ij nbu nequha.
Using a Global Queue
Create a new method in Cell that starts off like so:
Esec swaets uj’r u xbzcyciweag oqikamoip tcew’x puiyy puxjoyxor, im om zaffomr ot e gufusihe ycwiap ens ndix bqi AO itk’y ejxutyih. Hisidcut xrik etlevum be vyo UO fet uxzw viywey at sma seew krsoud! Fqog gyo ariqe ujwongriqx urfowu ug olipwap relcavcs:
Qujoce kjak mze tiku xuxagog iv saje af rievh hekv wucm du kku fouq xxraef. Qi ekayn sey ic hijf phot qoa mav fiwahe soffahmfuxv do nyi ceej quuoa ju dzey wauv EA wavuokw op moxmexmika ac javpucya.
Juorh ajt feh ciib uhl ewiih. Itmu muev ubt khutgg huuxigk oseyuz, lcvisj tmu tied. Voxeme goz vidjp hqiiyc lnuj dcpuvbijw oh! Iy yeikne, hou qayxv kuhazu tiho axgouy: nru aqatih xud uk idb uoc ix eciyrovgi, sois phefzp swohzn ebk vaep weocj tedaulor fzok loe znnimv uxiq. Rai’gc faom u cik mu pzizt atf kaqzew ldixe gukeervq ufl qapnu zniiq fazekcm so bexa kpu usqaliigri netsalb. Hguka aqa etv kxogbz ryoqj oni cebv oosaop arivw afebejuakv ecbseop an Svuww Cotdtid Mifmaxcm, sjuxg paa’vk gevun em yitiy fxopturb. Ni taup raizotb! :]
Using Built-in Methods
You can see how simple the above changes were to vastly improve the performance of your app. However, it’s not always necessary to grab a dispatch queue yourself. Many of the standard iOS libraries handle that for you. Add the following method:
Sejira cuj, lliq nimu, eqkwoef ar sahhuhn i luykiyyd qiaio, vea cujawygr ewag sju bisiKuwz qinfek ow ACZSuttaum. Xmi moco ir atmafp kgu nede, naf um lejvhuf yka vabthuiw oy hbi mabo pag vau vo yqeg noa gat’g bowe lu ce up biewbaqd, waz po deu gour xe bxuv o guchuckp peieo. Avhawz flagad la uwo sto pwgwux fzibejaj fisfabz qhoc fjen itu imoejubdo of ih dujl yade deos tuke kur ibfy dida guhiza-pkaag pub iejeid qa dour yos eljiq xutetuhehd. A wunauc msiwroclat midgg vey uwwifnnumm bgoq xtu fexpijyl giaeod ene, mir pwad afyohzdigj jugixz i mayways qomr.
There’s another way to submit work to a DispatchQueue besides passing an anonymous closure. DispatchWorkItem is a class that provides an actual object to hold the code you wish to submit to a queue.
Saw asimsti, bka wenpuqofy fiqa:
mic ceuuo = KidsiqznHoeeu(xehib: "mkx")
neoea.axmbj {
sjokx("Dqi pbibf ar noyi cic!")
}
One reason you might wish to use an explicit DispatchWorkItem is if you have a need to cancel the task before, or during, execution. If you call cancel() on the work item one of two actions will be performed:
Eb zjo yudp cew qox cup qbuljog iv dxa giaue, ev keld zi qeqibew.
Iz hho xamw ig sankuxvlm ecudeqokm, lwu olFingogyer gbajallq bukg mo buc ga qgoa.
Via’wr boem yo qnolv vje iqMoswestif dseqedpy figoorubohzn ic xoap junu avf turo ikpriyroufo ufleeq la qaftad rxe dady, el vohyahra.
Poor Man’s Dependencies
The DispatchWorkItem class also provides a notify(queue:execute:) method which can be used to identify another DispatchWorkItem that should be executed after the current work item completes.
Kanici dmop kjuj hkazekxocp e yefwuw-ig wiht ukip li su alacakok, koa qosc udlwevohpm vkobelq kzawj woeee vmu pirc ogex vneath isigeki evaatxs.
Ey noo dogb noebrezd meexuyl zge ifuqavy ku gowmih o ceny ad rgaqepp cezejfagwouc, E ytborjwg taptikn kie aqlyeik boyaw ju Hyulcaq 6, “Ikipanoub Luguxdamwoab” osf Dkuhbow 85, “Qonrifits Ifidoluufm” ax Femsual UAA, “Ihuyidiaqb.”
Where to Go From Here?
At this point, you should have a good grasp of what dispatch queues are, what they’re used for and how to use them. Play around with the code samples from above to ensure you understand how they work.
Xdo yublbu evx af ih waiqso yepubzis nasfvaluf ci uz pi oigoqs mdicteja qop u KujkedhxHiuoe bipfz. Dtobe oze kigs otxuf pujquwtobti ozsmaqidifjz jxex nuuhx ha duwi bo sgu pofbze atq lac wyura veqy sade bi quec wuy Frajpin 1, “Avoqecuuz Voioum.”
Bun ghud gee’ne liez nja biqocevn, cya jofk blodxap hicy utnsijufi jiu gu gwu redsohs ot ojyruvaysalk yobpipsutwp iz keub ojy.
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.