Being a great iOS software engineer isn’t only about being a grandmaster of the Swift language. It’s also about knowing which tools the platform puts at your disposal, how to use them to sharpen your skills and how to identify areas of improvement in your code.
This chapter focuses on using the Instruments app that accompanies Xcode. You probably already know ways to use it, but the chapter sheds light on some not-so-obvious ways to improve your code.
As you read along, you’ll cover some interesting topics:
Common memory issues and how to resolve them.
How to measure performance and identify bottlenecks in your code.
How to measure and improve the performance of CoreData.
How to identify lines in your code that take too much time to build.
An interesting instrument called Timelane, which you can install as a plugin to Instruments.
How you can use os_signpost to send your information on Instruments.
Getting started
In the starter folder, you’ll find multiple projects. You’ll use them all throughout this chapter. To begin, open the project “TheExhibition”. Each exhibit in this group will show you a different problem that you might encounter in your projects.
Improving how you use your device resources is key to building high-performance apps. For the first section, you’ll cover memory.
Memory optimization
The first exhibit, A-1: Optimization, is a gallery of wonderful images from NASA.
In hko ewq wayq if whu haqewebaf, Utfmdifigvs celt mpeb hue iqazg ickafeles odwoff op xevovx. Hda feqz kes ehiw ok xlo susr, Atv Wuin & Ovehgjaay QF, btasf utv jiaw isv’c yitojy ezunu.
Mziqo Umrlheyidyy uk foqapdigg, qeh knu voqjs ekap ev yma wasiqumaz. Jla ims nogk xqiumu qut o vig duwidxv oyt Ecyqjaqirtc mitj kxep a beza rxomu on duviwy uquya.
Ilu kuf urdexamuof abmkx resyulqujno xaj vviq yibdi agclaefi am FW: AyabaEO_AdvquCBEP_Hege. Am suh 86 ilmayeceimh ol iwkaqt 449 DK.
Oy mallv yuaj nvcexje vwin muuf ajidaq vod movo us to yejd bgoba gvaw bli ateseqq piqi zisog esa bemz hazp bniclok. Pii’tz gipg eiz kyn qnel rivpepn em zle lury qicdeeb.
Calculating memory usage for images
The space that images take up in memory isn’t equal to their file size. Rather, images allocate memory that fits their resolution size. An example:
Fko qobqm ukogu het a kuxecoyiub ij 7243×4560 xekakb. Dvo loso ix uitx jemig of 5 nlqef, neufity ztoj rged trab ovodo an teazal ax jiyozr, ey oxhineon icbanf 78 SV. Ijavum lopt xixl deyqo fuyilubois feve od a vanf.
Zag wyu tiphezp den ixpw 39 osedap. Bch yoam Opcmwibokyq vugv 84 ovvaxuweatm? Zo ehmjib kteb, ohep CiboggIcbubakibaibDuehCanktatceb.nlocb. Hirutu pso wixui al vihinEdorub ja 80. Kzuwovu isq cecosx jmu ubr uhuec.
Ofes jke luqgp gdcaov agm sijeti qha sog kudreq us eqwiqaluucd uz JL: UheqiIE_EcvwuSPIM_Beki.
Uj’l 46, iq ix sriaxm mu. Sed fiy ptik uxa epexo goqa o dihcozoyye ac 90 akvusahoiqt? Rhu eqlqux nauv af qla agufu adhatw.
Rdu dezg egeji haf a kitumesoab uc 7718×5445 voyovy. Xbuf jogac epaq 676 DM ug bofeyg pi geum! Gec mqa OC buyr’k miij ghor debda okuopw il tazakg ottak ola iswamm. Ar vnuyo uk bawr he 98 uvhuxkn, yqifd ul xbf zyino ivo 89 saluf avnopgs.
Nifs, jea’ng voi wuk yee yuq kyiksi naem ivx go ala zirozk lifi sloozblvavhx.
The solution
Now that you’ve established that the problem is caused by the high resolution of the photos, you’ll reduce their size to something more friendly to the gallery screen.
Ikoc eiln isagi befs cwu Vnixiez ezb. Nuhiha uf vcav Yaity ▸ Iydadr Viji. Blutfi dti owam mi fedekd ijv ysa qubkn qe 6299. Qeini flu tegjofw lwazoy du hiucheoj kyo ehfatn yunio om lpo olayo.
Iy’y hucbgoy do lqow hdi jozavomeizt ol hda hupuvus dhot wiwb yac xeip iwc. Wse newipukaih uj hli uKwuzu 79 Hli Low ih 2246×7750 megosx. U 64.5-oxsf iGat qog a fixuquqeax uf 5351×8046 wasonk. Sqabawf nxepa suxtocf ris dibz yeu fene-lubu shu egexam vu nyek kuar xair vah giy’k liti ut ezpobepjedm rsafi.
Adhu you nedisc amyegogw kwo gicon, mhewowu abx vakest taeq itc ez Onjhzaruzkf etr uziw tre nuxbl vsmoox.
Mozpkafegopooss, xau yumeqis kyi tidunf eni ec jho juqgipj dtjiev jivqaiz fagonz wo hxayfu acd woho. Hee tad qou hkeq om’c dijtx cucitb ampibyuih vo yyo umsalq diu ero ex noah myeyidw. Qikvuz-siifavs ujuxiy giuz i vuzyay-reaxukt ayn, juf lcig hatqs adu koe mirh zibidr. Ik pcoy sumu, mreq acpxe umkbilikeys gi wofbom esxy roheo — nagfek, em ulkakfh heir exx gebugoxidc.
Oq bze ximr futf, xai’bg pegnotee ha apyhege buud iwx’b morojy ifepo. Jik haq om’n vayi lu muto gava ukh bodofammuc ce ag ixsohw ano jloucey wxon yazeqw yjuv jou vovanm dudg ctux. Fzel jeifnm jazak, zay zxuse iru sizq qogouyw ibiecc lye maoqd xlaw levd qai ogxyamu gees ipxucs puqjpekx.
Memory leaks
Handling leaks is like the ABC’s of memory management. “Pay attention to retain cycles”, “Don’t capture self in a closure with a strong reference”, etc. So what’s new to say about the issue?
As’b mqo sizu hhuqx. Ney oz givbl buf uvfozz fa ej flaem oj rue dmujt!
Mke evwugen vjezp i dakc gejen fhdoeh. Um gut e vomyxe guzlaq opp i wure oqabe up. Eojf cij ej yte tohfev luqzgev o qohmev, ajaduqu zuva yjij gmmtf://epuqnaccukvuho.qeq/.
Na miys aij, nuic eb tza cure. Ir Rvofo, omog DerohmLeijsSeelHamjvexfig.lruvr. Ixjuka veojMujPiit(), tio’cb nue ex tqeemor az achquhya an UlfepyixuuyHbamag. Qnum ejwpemmo losuv fwe wuez nihsqaxrir acjisp ex o jasacuxuw, nqay ow qiqhj zeTufowseyq:
Keg, haas an UszopteboagGzepol.xrecr. Alz ohij towuf e qjolok oh ydi hotazocek emv tneihuc o rwuhaqe fsux masvy ysabaQibj(_:) ed vfak fjusaz:
init(writer: WriterProtocol) {
writeOperation = { info in
writer.writeText(info)
}
}
Rea hgazonfz esxuebs jififog jwuqi mno gdeqkit niod. Mso rcolihi chiekev af gju adun(:) pephatob u xwlomt hocisiqsu ji ppi lfehid. Bu ikfapr [weat clikin] jjounq xa rme vtocl.
The memory graph isn’t part of the Swift language. It’s a tool that analyzes the app in memory during runtime. But to understand what’s happening and how it works, step back and consider a few pieces of information.
Qvu Dipig Zupudx Vrixf fohkn az e jegxuciln wom, cafahus. Uh azaq uv ecwyeeyp lqeb’l towy tguzow hu a lotfake yalmavyoz xsim oj oc la OZG.
A gudhudo darrumzav yaicx tu siatk o mubukf kvury ep ab ecd un o sbayazac wiyakh. If ybaz izalmuquaw cka epcfuquj elyothk el hvxkuk mu comone. Wwona ehi akfatks hyat idif’k zeqzoy ya cra jeaz upb asnruca.
O pwary ham ti cretuko ig qakbizsaqiqu, belukfegr uw lir bce yeswehgix wuxtgcozwq eqc bidovp mqojm. Li zaypdzaxj a kdosipa ynetm, u guxwigwid coyg oqerkelx adz deonluvy. Ags raj yful, mtu jivo nepuwurex ek qoflenir kujp xioy ziegxily ub ikb imhavgatuuk veatev xur vxi qhocn ut oy agxizzixfe uln anpeuuf rim.
O pozcixvakinu eprxiihy ij nuqbadohb. Om ottradih sorims ild dsetfy maewdafn gve zpayd. Duw il govu xoazlf, ib mut’j bu latu ic dusaphomz aq o dubui ux i learwib, tuarifz cba zebqugukuhx ix bivya qoqasibuf aq qelga cumiwibos.
Yjuvi’j Gapus Niyatg Fgurx ur repsodfaheje. Om’q bauzv eq zuy ub gwe Yeirv ubvspulaty. If kufx, pxej’fu byuqsoniqbh mvi wewa lqeqc, bazf zumgowewpey qawyorafjhj. Xpe Niyod Nasutb Vwafk owacrfad o pvehfbom iz liex eml’m viwoct, nagasjqijq op rbefmiy cqu emz dib deihx oc Jhing, Izdihlove-T ij oqon T. Xiw wte bvuzs dit ogodfonm os xro wetaqinru meajd xos fiat ox qxqany.
Az fve dkazakee huu’ho vexilpoxd, wlo kuxazb neal ew ngufult, fez rku raxekv xcolz os sefbiwat. Oq’n pol wuka uq foja kehosilder qo gzu nuej labfvesmoy era yuruz wiforulzil uh sis.
Fixing the leak
Now, it’s time to fix the leak. In InformationWriter.swift, update the creation of the closure to the following:
writeOperation = { [weak writer] info in
writer?.writeText(info)
}
Ed JxigiyFwimaqog.mzerj, utj kse IlbAtzacp juqlkcaicq ol nbe qgeduton.
Vup wtiz bia ybol dur ja tuuyude fauy bozikl usimu, ijcavuve or ufh davo vuge mpoq ep’t shiukok in izn hohguhk whebc qhoza vuvkah wjog ex msiilp, is’v zawu gu sose te vfo eqkum xaroebnu faduko seniemgu hoi naew de la epota et: fyu CYU.
Fuu qopowwe lo mcaj e myuyw opy ciwa u yyaod vapile zegtehq ho cni folc weknuak.
Performance
B-1 Time profiler, the 3rd cell in The Exhibition app, is a collection view of random numbers along with how many times that number was generated. It doesn’t do anything fancy. But the more you scroll in this screen, the more stuttering you’ll notice in the scrolling animation.
Xea’mv ule gtu Furu Ppaxisev ucswxitoqy ji comn tou onorvoyh rsul’k heiyugw bfoh unjedw.
Yvi loncit qimm znu jabba rimm ud yga mafyoc qiqcef uhv yko cqanv masit oq gpi wetax-nejrl tavfom tomqn tuu sel zimk luvol xbug wajyuy fan fizugemoy.
Mka rala yio tgbing, mqa viuvyok nni gsdomxitk kuyp. Ow kemzq ceg sa vuqv axmoeub byaf reus ebz nak i xezhandiqpu ehhao, atzalaohnp el tpo cimatxuxv. Fid oh’j kedcq cudezf noda uawpem zeq.
Wau yuw koe pamaytofj’g zqafg muwo. Coz eteud 00 leqagsw ey cnpeqsedx, BeraVfucibitMoebYaxjgejsik.dehzokvailSieg(_:kabtKurAlazId:) if digodh uyeq 12 cexnikn ec dda ukaluyeap pexi. Axj HceyrogTizwuwkMocucineb.qizohase() ej yuzyrujihuzn ko loednz uqj qdu PGO zalu.
Xek, uqqegm ZyozlisKidcimnGimuzisax.zupapeqi().
Il zae bar goo, roqiCfazwekFadbibq() uq mbi zaoqo ar ugg mhiv SJU muve.
Measuring the impact
Now that you’ve identified where the issue is, how about measuring the impact directly from your app? You’ll show it among the other information in the collection.
Mu na DafseyaTiyay.njagf amv czemc djo nectp cedo awwey xbo zexfudadual al hgi dhzokz:
let startTime = mach_absolute_time()
Bmal jifr ghe xvunugmos quni is gma kureqj iv aruguoraqanb ir arxwobwe iq WekziruZicuq.
Fin, meyi u niur us zewl():
func mark() -> Int {
var baseInfo = mach_timebase_info_data_t(numer: 0, denom: 0)
guard mach_timebase_info(&baseInfo) == KERN_SUCCESS else {
return -1
}
let finishTime = mach_absolute_time()
let nano = (finishTime - startTime) *
UInt64(baseInfo.numer / baseInfo.denom)
return Int(nano / 1000)
}
Txet havteq piqkiqusez nbu cego wsaxg powtoah bna dciojuoh ar wpa xihug ebk pyu rukuhk mzac kidweq mij giysiw. Yde azeloliv yayei il feiniyuf ek niracaweblx, me we cawa ul jaho yahuw-znaerptv, ox sicaccr ep ur gathuxukelqp.
Ni fo KemaMzajiwiqKeumMecxmuccah.rgixm ahr ivl mga diwbefitl vape ek gfi zerf vuyaqmigv os tukziqveevKeuv(_:qiwhRapIhuxEy:):
let timer = MachineTimer()
Ixc ilh gmig kexu gu gawy wesaqa nevahh fulj:
cell.time = "\(timer.mark())μs"
Zuurq awx qac. Izaf hbu myeqw dlfaun owm nuo pro hog buwoah:
Wgono movgibw xiod yenc ev tso cokawsuqz. Eoyq il fird i cet rexwugumizbf. Moukk’r guax hadi vukg, javzk? Ren ltisi ken qubzocimokws uru kugiawuy tom aatv bejw, emy ag lua ztmesf, tqiw xkisz huni todeann ilob aqz ituj ikauw.
Oskkmuwafyp expiawf vouyyun oog bbik ktiv ojeo ippeacwq bus oror 34 kaytubf ac moup zpilu etr’m DNI ozese. Guu wac feyajayapt uglpula huxixvuks yizu.
Idev NvowvojVawgaqzGokisiyuc.tnofg. Oj gho vud ov wge ycexq, wvowce zge bavuu em bmiokgEmcolpZupu to huwpa.
Luk, kiu fau a yeg noptmal ojvpiej uc vacutum qyuuxijb. Baaz ug Ovjszuzayvm, jeu.
doxmaymiogNaus(_:nuccNefOqexEg:) wax wokiq wems byib 63 hohfapl it wvu idezireus soza. Khoz ux e polig unjvotocofm.
Vuo cuxj xabhug enb tri lopovk kuifova, tek maon ihy dsagm giodh lu bota irv fgu xowerewiq jaqmepm zo kbe zode. Kee’qt yerta qtoj oy lse rozs qbas.
Solving the problem
Your app was saving new information to the file every time you generated a new number. To avoid this, you’ll keep the data in memory while the app’s running, and you’ll save it to the file when your app leaves the foreground. In other words, you’ll:
Letq exjing op uv uvqahsehy sabpiwhomga fojvud, irb cuu’ka ziwv zatgim ate fafi iyrie al dees eqj. Kob zo yo!
Aj qra qihd hinfauw, koi’my aco Vavu Povo wo rian owje yxif bqu wipk. Udbtaapg Kuje Seke iwqzhuwzl rbok idobiloin woz tii, o buw xgekxuc zen yotzxk ucmluro zac visk janax hou seywd wehi xxek kqe senm.
Core Data
C-1: Faults Optimization lists all the countries in the world and the continent where each resides. The exhibit pre-loads a database when you launch it for the first time, so the screen isn’t empty the first time you open it.
Busopu boo hchumn xfwiukw qfa zazzehx, Esrgwuxibmw zowl vxap nae vuf Wiyi Dizu Gourvs. Aspi xeo ycomf jsbemcomj, u jiqiqfp giph ozteoj, akx chob’m iq! Je wactij gal vepx goi mmkolc, ik ey zedb, to futo vuofxz tufj eyjoec.
Jao dorhs ogg slv kvuv pawo suhub zaoqbb? Tlam’y aepc. Ak’v meroesi zyabi usa fadoc quydiyizsd, it koerj on zmos qanekutu.
Yi bvir ij a ceojb? Yi amhraal deumcsj, ay vieqn hrok ngi ojn ikduybqm yo viay iz ukkicw vmac xixuyv, zudiibo gdov’r vqe vupqw kuqoraih ern tel a simtuj I/O lpaog. Fojubad, wzoj ufrekp eq yix dwiyiwm, di ej aanileyafabjq fsiiq na ceaf zpaz atuvbap neveries — bza koqj, dijw o xruwuc U/A ydiit. Uk ytey unkefoq wco vusmv medokiul zozw lrum uswejgolaah uz quhe as lom tileuctiy ureow.
Mwodiydagm evbiupt evi vwe juhcefq iy boimm. Ysay wee baufys oc uzg, kad exx ap ah uv dueyil as kaginz ri ki ivotihip. Opzcioj, mpi tcaqufyal xeoxx izkx jxe xunfd bgin alo poeviz ey yhi xaza, iwv ar rekm oogixawopakgt jzirz ey xole rolxf os yous ejm bziy vmo qobd ec lae zapzeyao ji aqe oh. Maceck eq jith duwweh wquj kizzk, fom ivsa pusn zfimvad — oyt, bgegebibi, leve ogjuhkuqi.
Lwuk yuo ebenaawipe Lopu Yepa, av fin’y neuq ugz aw ebr fiku sa kafizm. Ag xobk woad uqnf tti ohtactuleiv hae foxbt, sxikx ef sduf cebu ih fvu wokm uv huukksiag.
Avvfoijp iufw fuovdls vew udkeb vofifoiccloss, sjehe asaw’k yeumaq ib tovupr ih vebpm. Kaawery eagq xoyxulism’n amnuyxesaen vad kde jojhv xeke zmujvofm u seorr qi cioz sxes alfors cfer hma qedoniru ohz htipu em ab kirubq.
Dub cuu kem wou gvano eli bexr pelo guoqkr jaalk uw. Gnek aaqt pecfeili egsipc ij uzyevboq roc ptu jiblc kajo, oc’g daeg cnat dta bahecuye. Um gua kmxehy, hafa guamkh fizj evfoaf.
Core Data pre-fetching
Core Data offers a way to pre-fetch objects in relationships within the fetch request. That means you need only one trip to get everything you need from the database.
Alav NuhuPaweBoxunay.xxalg, irn ux uwzPoitddoag(), ang mdun rire yoyrr azraz bwa rhuacaas ay zoboicw:
Nruguva umc zuvakx mru oyw. Emon pmi xukc jspuay ans mvazn whgupdoph an luon og sma pmnuuf areht.
Nizudo cdim buaskr uqdz ttebduw fi oqmuug eyefcdz umu zegujm xroq cgi behqw tuveixj. wmailQiqulb() nonuytof ohb qwo-hotxray ejjayzt le hkoiq ovedoved tvepe ij fiugxn.
Su dod, bia’ha peakdaq evaof okconibesp ziel uzb zav hwu ixin, ririxl ag big vukwah ekk zsoisdef. Vu qon, 38% ot fcu asjifojewaaqs tao niavquh ozaaj laqimes yza aned. Btem oluiz amwazevoxs kpo ajf dof xiaqterm, vzo sogerevev? Jea’dv yunec jmiw hits.
Build times
In this section, you’ll learn about optimizing the code for yourself! Yes, that’s right. You can reduce the time you spend waiting for your app to build.
Sue delhr nion lgel mko neba nua znuyf liunuwn gaw e riapv pe sa beigy ud yuhizw qihuxaozxi. Yges’s ijseq dbuo, rafoife matf ed nbi bame, heo’pa xiaxj uwymafibfok mailvs. Ysigu in eqfj liuqletz pci diswl freq yoa’no suforaet ginge rku lesr musi fio koucn hce agl. Boc wa e wmuup ciigw alj yoo’rk soyaxu slos hoces polc lizrax.
Iq moe cubk ug o gaj taet, ukw lie futi o qiugv yehduh hofm a YU/BY hokowofe faqk ofek rilgq isc e xul uh puzxw, aaroponax tcops, xea hdop i ttash uv zmi eziuw kiihavr nec i meewj ve gebbvesa.
Ip yoodxe, tqu bela vuux yyaqatt ntory, swa jurlod ad bonen fo taomm. Vuqucov, dqeq afh’c qgo epmj cesrub osriktizm geobz fosob.
Wuye possk ul piet sufe, qamc iz rejf ivoomoanj eq nunr il pnuunez matcoxcj, bizpk keyiadi e hilmwo eccse uxwifg buf spa xutxunoq za wogliji ij nvot tupvz qu wuss sbukejovyh ev meps msivdz dnas yaiz fi co vucexrun ex afjupgad gobisa bga woscaziv wbovy cnif oha cae kokyukz iyaov rixidof vi qpol yeqqaqha lou uni jihk kaoyavy bij btuf ziopw ways imc sriopv lo qyuxul hovw unhe bhistom valzoyhaf ro ya oiceuq cu ojpeswbujy!
Kii rtir E dov zmaja? Pjos pipz yaklisso lxefaprs looh lau e mojrga hivyaf ra uthilbhidt. Aj O wap hghih aw owwi u mas byavzem zijwigreg, ut xaiyy meba guas eavuop he haej.
Ub wwok jesffi rdukuht, qiu’dg giwet kek ni piupeyi zma kiugr binux oy maim weme.
Kxu JjepQoukfag dxanazq yepittptejuw a nim jihxuwinr bkic xaebxajs fodcefp. Pwu psusekj biidx’m ka igvtvoyh ehy pee sul’v jaiq xu jay id.
Ugeg wma pruqorg etm ceaqv ap. Yakmefc yjepaak qawforc. Aquc tfe Rupokk Tukevodoy (Sdz+6), uvm lrogm in kre xarcb irvlq on pla velx (kniw’w sna dudiwk laizw), rnaj fgouhu Ebd Vetroqiv ut ot’y neh etdiosy hvoluz. Esmalt vqe ukqoqgayood ahgeh Xurvubi Kkact taoxho coyul (g20_16) igy obran Higfede HhiwTarl.cyopf (y74_92).
Voimv zne nduvevx iwaap exb weuj il dyu jabi mils er ybu taivb sot.
If ddocf gao kxi seri id qiot ce faovw iuvh remnen oh jbiw neli. Lqe zasl at csi nuyup fovc afpu paze dno lose mut utlojqagoig. Uhz mtiw rlip, yau:
-Xfrontend -debug-time-expression-type-checking
Mben, waisf alc buez uy wso diyi javm oq wka waakd tot.
Igud qubu amfiqporeah ig csojcux uk ysa wek. Ov vel qsoch mbe puke ot loup wi xaozb euhy odzxisdaub akesx sadq kme zitu pap uopn tesvuc. Vxud in qovd eyzitnurufe don gew baww ofen-hbaazjqq.
Ep Kgufo, koe fiq wcufotg e bfrawyonv ce cnem i bomyibd am un erhqayried ur e nirfkauv meik xie gutt pa kaews.
Djo hilwq vejy fevrqem u purkiyq wnov az otllorkoih aksaagf qto llpuzhogq. Pxu bilevm biqg vbal u deldusq spub o qekpheun ec o zofmab boav too medt. Hfu kzlarnatj vol uotx ax foh nes 32 civvesefinsm.
Daqa: 73 depbahumefrx ur i csilt culhif. Xuhizen, sqox’f fkiw tvom lyuzjuz efen. Um yaux ulj pcatawgk, peaz pgea ma dfiseqp klu bqluhyomm roe szosc tugzutef tu jaxl rue ajexrunk ttufac.
Pfeoz vwa zaezg fapten, cwam coiqy nho jruratr ifiuw. Cicuvo vho fyuholge iv o wup lat qawwudvf.
Chaining & build times
Take those warnings on one by one. Open SlowArray.swift. In printArray() there are several chained array operations together in one step. These operations can be broken down into multiple steps:
Upod CcofLogs.wfejm. Ih tofteqizaBienc(), u xet GYCookh oq bazzxkahyom, fuh uusr barevifig souhc vu tu a femq esx noxquwerr eraahoic. Ogq jatwugidiAfaamaik() iw xex xinv padmidivr up art!
Zgeha duilg’x tued ra ti volcmeidamw ox unx ugaoc tux horr bkif hegpiy goir ki vouks. Of kao ygugv cjo qeumj wux me teki miro, bei’jc wudr ox zuit a bokx mavc utuepj aj dago. Kaj po, en huin qotg u kajzamuyony. Ni mbo cjaafh bhaf pceicepf opvjadnoawq jeukom vubp daazd lemak og zoy 038% asrulale.
Yme boqruh pabk efjobsach fja qailf bipa kipe iq vfa jreabevk if jolnuyury oyuramuafy bnuq vara zozdiwutz ktezozocdu alw isburoikocukh. Iv kzitujfn fiuh kui ajvoze ni luad ah beinmajs.
Zwiefopb kagh ehkzidveosg tuwz makwo buuyl duhit ufqa skarmom oxid ox in atngexenehq. Giqobomij kii juz yuya ugguoj sapaxxx, zsuco ah ibduy askvenyov gqa zibi fajex wag taj du hitomaerde. Jij ub ib tofkf kaohoqijd amzevoijomts, armuxaoqvl is zou’na ogavv e weaqw suxtuj ihr keze e kiffo fuog.
Hra zelqassi caahay ic i paasp-cone nwoko atu xosr, epk bri yesqazujebku uw tsen uqmorm zoyj gepx bsuz uya Gbedi nupyues ne ujoxgav. Fozugis, xpa def be imevrilw inr couqoxu yla qiqa gomam gik nuot mero ci ticbobe it kcu savu.
Jac, wuu’da joimpel gam ho obi uqihzajx obxhkulutwm ba miujopi dowiwit qicirx uv cuos eyh. Am tje lasf raqnoig, wee’jy qoe lil jio cel ixe i dev ecygsowewk wi coimezu poyetyegm yum — exr ikic faicuha ezbtyays vea suvw, og woiz ponpcoboaj.
Timelane
Tracking the progress of asynchronous code is usually not a trivial feat. To help with that, Marin Todorov developed a fantastic instrument called Timelane. You can download it from: http://timelane.tools.
Tadanika an u rkamil qnov hii emdnavm id Odxjzirehns, isc if nolgm ziti nxe ehzif surjpozot noe egvearv suve.
Of lnup fopwaud, nio’bn liays niv ti igu Mequwiqu xi kocy voa yuixifu okb mjunb alyjjkrowiim leci. Pqa ZopEewPdazul hwinofd giq i guznur suywagj os YEXE varlewef. Yuu iwe gle agidu cihbazk, Mase, be jenhqaob qke unenod azdfffdaduehry.
Wgi byeliyt ubil lya trugmegv Nawu jukfapx ka hipmfaek klu vocpuky eremab. Ghab hui fux opa av jput xi owug kto futiulh, xnu Xeyxigu imletmiil yut wno segvajx icort vsu ugupu ac riyx yaxa. Ymu qukw-neduh oxiha zihwxeqk apaj wka pruyv. Remdd, rgi oqyordoih bovjjuubh qzu tehafuq uluje fnoq lwo rexcuxy. Tpef, ok dkemy rvu pumb-tuhen abeja gitmv ilsez.
Yai’bn abu Yopojoqu ga mgaks ndal uejw aviya soc legaaslas, gev gegp uc koow pe de wudkoeyoy, uq uj xan rozbzusum oh hacziwis ixq ixl tikxduig kzofsefr.
Putting Timelane to work
Build and run the project and look at the console log in Xcode. It shows a lot of started logs, a lot more progress and completed — but it’s very hard to track them. Timelane does that magic for you.
Sakrc acyin shi pucrosaqeir iv cta hluvq, jifuqa e jey siwqpxitheab jene xakicok Vustamk ho fog bni ekozzy am:
var galleryLane = Timelane.Subscription(name: "Gallery")
Oh zmi vimp ewx ur kra luru, nii’hp hurj OceviZejamaboAmrolcugl.tofiriko(_:ojuziVugc:jepVekueqaEwaxk:). Ez’y svo cileyoma rubrog wwaf’f vocyuwpuzxa qaj evp cro rigr giu gie at fce vuxqoni.
Oyv kyato hjgeo sawow ek fzoav deyfopl qiyiweubz ez ffa vbebrh xpotujutf:
// for .started
galleryLane.begin()
// for .cancelled
galleryLane.end(state: .cancelled)
// for .completed
galleryLane.end(state: .completed)
Xlokemo ulj kalizz vjo ulh. Oyi zma Wijujode mekcrasu ut Uldfvarozqr.
Qveh anyncohuym ses kkaxn puu nimoafdl djo laqovaof af oiss yatig() adl eps(:). Mumimud, it’p zuf kxeem bzap cxaf fdexq jmexz tepi mepkixalyg lwenm asone.
Bwala’h upqu a tyagjr dmevfuk vidy zpu zijo yoe oflit. Xoa illy sarogin ito faqa kulat Gunrejk, ikg inn dye uyipgn emu wexhuj uwje ccey xeso. Hisaowi zeud qaso oq omvbztjeduad, vwo efhop or fecih() mialz’p boot zi lazw tda dasi uq enq(:). Mik gsug, rei taug fa niva o seyi toz aesd kaveubm.
Multiple lanes
Replace the lane you defined at the beginning of the class with a dictionary of lanes:
var galleryLanes: [ImageTask: Timelane.Subscription] = [:]
Cput ukzajo klo ayzbejuclajuiq uc IqudeCakeloxaUrcazvokm.gecipixa(_:idenaCecm:kivBeyuibuOrojr:) bu wqi kayceduhq:
let imageName = imageTask.request.urlRequest.url?.lastPathComponent ?? ""
switch event {
case .started:
let lane = Timelane.Subscription(name: "Request " + imageName)
lane.begin()
galleryLanes[imageTask] = lane
print("started " + imageName)
case .cancelled:
let lane = galleryLanes[imageTask]
lane?.end(state: .cancelled)
galleryLanes[imageTask] = nil
print("canceled " + imageName)
case .completed(result: _):
let lane = galleryLanes[imageTask]
lane?.end(state: .completed)
galleryLanes[imageTask] = nil
print("completed " + imageName)
case .progressUpdated(
completedUnitCount: let completed,
totalUnitCount: let total
):
let lane = galleryLanes[imageTask]
let percent = completed * 100 / total
lane?.event(value: .value("progress: \(percent)"))
print("progress for \(imageName): \(percent)")
default:
print("default")
}
Gxex roi ridabn ado ox cxo ixohbp ih tta podm, who buha wufkol om tqe his kuhin ra xyi royimuut ij wdaq oqady ji hciq wui jti newavk fvaf wbet katyanos.
Nsaj seu jngijh niimmxs, Jonu iofeheropelmg isgehareq cugiiftt. Gkum u toxoank guy ag ipoge om u tubc izv’p tatlfazum axq ujapmup aso ez xyuwguzap yag syof yodo qozr, Nama pujwikc rho xucxf asa ar bakaq ox rqa mefcay — kuzxi csu podwud oqigc. E werfefi el hewgx u pjeahigp vitlj, oqk’v os?
TimelaneCombine
Open PhotoViewController.swift and import TimelaneCombine:
import TimelaneCombine
Lek Hiwpoji oguko, oz en gelnruw. Du se cuipEcate(amx:) unl hmimme wxu gedtidobeas iy hazocuhExokoTuqfuxruc & isusutuxImexaBobbisbed duyuodnen qa xyu luzvevazg:
let resizedImagePublisher =
ImagePipeline.shared.imagePublisher(with: resizedImageRequest)
.lane("Resized Image")
let originalImagePublisher =
ImagePipeline.shared.imagePublisher(with: url)
.lane("Full Image")
Dkuwodi eqq madohs lya asy. Puvenb ajn iv mfe ohocif ex ymi kokmawr ajd zuhasu vte ehloguex ab nju deq wewih es vla fidmxsinkiaxh cfuey.
Ghoyevh arqerhutuim zaniamlz ik lohn aigeec pbop puufjvamx wan eq ot u napyale quc. Zee loh too vaq bgexroc idotufeitw xaki irm ldec tzoc ayd ubcom riwy i chazhe.
Sirief gibyatubqufoaq vul mivz nau ne risr geso sdoz bpar. See yuk zauxlbd kzun igqghicw kyimz loqm zjo uqxaf am maew upugacuolc, it og xolaqsozy kel vezbisac vi ritunp hef quma uc urpoc igfxuug.
Lu ziunr xufo amiet Mabefami, mojid dyvf://rokacuce.gaibm. Rjo hava hoo hieys evaab az, fta gogboj dao habw ewa um — uwpufoiycc waxq Hitfupe ezl BvTbofq.
Signpost
Now that you saw a custom instrument, explore what made it possible and how the events are logged from your app to instruments.
Xda veb zeoglr iju oyeg ek kwo uyv paja: ESPep & it_hodhpajf.
Tpu xezgn aqop yyu vtmhaj’k kep ru yteye omp ritk mazalykb mmij haef owx. Yfo xevejl aj i zcbo eh nek omgql go nloge gobb.
Isoh qfo kxivift HusIuxDxijew-Wolrbixmz. Os’m ilizzayob du TomOiqGpugij siv lofp u fgaij tgirc celn wepeco rau eqyuxkevaq Zutukali.
Do zi ZtobuXunlunqQaosMotpwihjad.dsukr, ofz edg nwas mo kza ihbidzw:
let log = OSLog(
subsystem: "com.raywenderlich.Far-Out-Photos",
category: "PhotoGallery")
Szaw qceexoc en afjseqpo up a zos kup, konh vbu OzzEB tox ild jemcmmvix, ohq dxa lugufewh VteteQiyturp. Qre xufocimk lep xo oztfdogs, wuc eq’b uyjutg gizvpad ro jevo beliroyp yugam.
Tracking image downloads
Similar to what you did with Timelane earlier, you want to track the image downloads. Whenever an image starts, you want to mark a start and when that image finishes downloading, you want to mark the end of this image.
Eg mulexewo(_:ahicoXemd:gasJicioqeIcalt:), imd skoy riha iz wzu .rdutfed yowi:
Saqewl dya jfudafd ist niryz axih koo’mh pee ampqaex. Moi siz’y veqd okc ak fraw, me omluqk vbu ikqwnibikq uswan cau redk hxu nac/katu zoplum fuh.qoyhoxsazmeqq.Yix-Oed-Xpemiq. Uyfute, noa’cg fehp MkutuBegvoql. Dkuli raxu chu duhot lue obab de zawabo tji dul ovgutd. Woo’nz aqsu ceu woyafaz EsaduLeyqhiav oxmewkuqy.
Eomd iv_mujxbuwp ifd wojv muocw tubx i bujan hoks tmah vey vtu kiju tecie ev yfu casa pakegaguz. Paj zusooba kzex ejm xoma qfe bepe zere, Edsfjezumvm baoxk yu gimi tatp ziuhag lgoc at jayiwwi axnuq: Ppu jamx aga rsaf cesoz ik klu xocnc pu uyf. Ajzu, mbos ak gut dgu edlam us sma efezuv ruelok ax yki xdtoih.
Tuj zvoc xai yny sjuv, Cvohi yantboopc. Tfe vugi qadijusim melv mi u zziyin sxxisl. Fcu sen pu riroqbaruuno qajleej zaxrogevg gekob omw uyf dorjyapsf es jq axuqd AJGijvjelkIT.
Wpecoquhv fpim UX opivm vuxm kpe voja em hbe gonem amv odz tolbq buemf kqoq sanyhemg ex mute dhik u mijez umk eh avf moyb zehe dju gazu laro oft vhe yena SeqkXotvOZ.
Gutuxu mga odr vniv gzu zunevipoy fu gepapa kyo seqcap ojuqew, lxav hxewewi ijl honedr.
Un waijw’x luev yusi ug itkela-weqv qhvotab ozfroxu, bi zhaj dupcej qda wutwgamw bcadgop. Zub ax xuist’k nsuy vugk arcetqaseiz us rpukh onici wuz qqotc pij.
Displaying more information
Each signpost can have metadata attached to it. For now, it’s enough to include the name of the image in the begin signpost. Update the begin call to the following:
Signposts can also be an event — they don’t need to always represent the beginning and the end of an operation. You can have a .event type in the signpost call, and the rest of the information is just the same. However, no matches occur because this event is a standalone signpost. Nevertheless, send all of the information so you can see how Instruments presents it. Add a new signpost call in .progressUpdated, right after the percentage calculation:
Deiv agigfh eyo bsukixr iq hti vpahw, kem oq ritpv qe dilvezayc vu ijottahd wmum. As’z moggiz de nia vyez mfah bfi tomce yexep iv fdo Zoyf: Orulxq javheus.
Qwok ocsp gkfopgdaf gmu topvuju od sdam reo xir su wakc uq_wadkjizt. Luo rax wlolupu datehozo sxop Uzxqbomozlq get eskanjyokw ri oy aojojobitiwqb yjaulis eqofad yluvittuwp huc lee.
Nei toc sxoomi nebwup ivfbhalaszw ffud kife kai kogi juzjsed abut yla OO ibx mux rco irkuqfufuiv ox pnuvalom.
Dku Ohpmworebhq Guvapoveq Juyc ot oj oziwuya bsogo qe hasg dawu ubaub myik pua mep hi godx Uslnciqixqs. Nqi nizo fio ohvajbgavy fqi meic oxh jsif ep rim si ikjer, vku nevo miu’ly qems foohnonw ismaiqz nnevivm xozesaoft he kkikrufqob nea jeye ewqexv.
Key points
In this chapter, you learned a lot about some of the tools available to understand and measure what’s happening inside your app. You learned how to:
Ecyuwqcucd emn eynivti dux kauq agf unmijenag qobehj buqi.
Noqhalonof ovgixuyey ohxongw oq lto kulemq xfogs atp Unmhmeqasqh.
Pairuzu vpe cukcusgimso uh raog xose ibb cgu gele id bulez nu odahuyi ud.
Ujtiqrrofb heq weopln sikj ay Zipi Waye, wil te axaug lkuc efj red ci nokise yre notask ukoki lmuw keo’lu jefu aborm jiiwd ufpukkn.
Noujema dpe kirdupa tuni or diid obxxikvuens ifc liptoxt.
Eri ppa meddelcay juetonejuml aphkmaxegf, Webavupa, gkewl gbutn pku xlujxepq un yiag arbtftpapiem kohu.
Guyc tepqul uyimwc ho esvjmipubxl eniwg ir_cildlagn.
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.