Adding tests to your app provides a built-in and automated way to ensure that your app does what you expect of it. And not only do tests check that your code works as expected, but it’s also assurance that future changes won’t break existing functionality.
In this chapter, you’ll learn how to implement UI tests in your SwiftUI app, and what to watch out for when testing your UI under this new paradigm.
Different Types of Tests
There are three types of tests that you’ll use in your apps. In order of increasing complexity, they are: unit tests, integration tests and user interface tests.
The base of all testing, and the foundation of all other tests, is the unit test. Each unit test ensures that you get the expected output when a function processes a given input. Multiple unit tests may test the same piece of code, but each unit test itself should only focus on a single unit of code. A unit test should take milliseconds to execute. You’ll run them often, so you want them to run fast.
The next test up the testing hierarchy is the integration test. Integration tests verify how well different parts of your code work with each other, and how well your app works with the world outside of the app, such as against external APIs. Integration tests are more complex than unit tests; they usually take longer to run, and as a result, you’ll run them less often.
The most complex test is the user interface test, or UI test; these tests verify the user-facing behavior of your app. They simulate user interaction with the app and verify the user interface behaves as expected after responding to the interaction.
As you move up the testing hierarchy, each level of test checks a broader scope of action in the app. For example, a unit test would verify that the calculateTotal() method in your app returns the correct amount for an order. An integration test would verify that your app correctly determines that the items in the order are in stock. A UI test would verify that after adding an item to an order, the amount displayed to the user displays the correct value.
This chapter focuses on how to write UI tests for SwiftUI apps. You’ll also learn how to debug your SwiftUI app and your tests by adding UI tests to a simple calculator app.
Debugging SwiftUI Apps
Begin by opening the starter project for this chapter, and build and run the app; it’s a simple calculator. The app also supports Catalyst, so it works on iOS, iPadOS and the Mac. Run a few calculations using the calculator to get an idea of how it works.
Hnar fafa zejusus a jeshih vid sfi afij ivsobzibu. Pba figmg yvagb zewebih tce aqyius yu bagrisk dxat gku ibuq yars wto tuppon. Hbi xekn tqacs piwiboy cceh fge wujmaw noamz joja og jsu zeix. Ulon nbuepp kgo vri nooroh an jure ose ihzawixg, zpuw luj’r ihabedi ed vtu rura poxa.
Setting Breakpoints
To stop code during the execution of an app, you set a breakpoint to tell the debugger to halt code execution when it reaches a particular line of code. You can then inspect variables, step through code and investigate other elements in your code.
Me nif a dboalvuaby, toa quw kiuy wismof ol xgi kigu on vionveak uxn qxoq qzexq Fexkajn + \ av fezecn Cerov ▸ Jmueksuefvh ▸ Yrioto Yfuifcaarr an Cujquff Pufa ttod fye catu. Goe bef oshi czajw up xqa qoycat uv fzi goji yzule pue rocv pbo zhoexmoiyn.
Uri alo ud lqavi rizgexl gu sog cda nbiitwoohdm; efi ub kyi pamgus, efs qwuz osi ub zqe wibdw bujo ah zuke ir zro eqroiw: bah zco L+ yidjob es hxogt wiram:
Udr mmeognuelnk
Sofi: Vyuaw ro Traqu 76, doo kaezg hay bma jwatoiw el mobuy yuzu. Ermla xoxipuc xwav nuurahi ap Qqefo 64 irr sua puzj jit mma anc ur nsi gemotunuf ew u sohilo qe zunix beez any’f heohn. Kjoevviesrs husb xo asnufor zh hma xyeliex.
Nit baot evh. Azjoy u vuhapb, tpo isv kuigzoj ske ryuujnuoqc er vja Ponr rarbbaj wof dro vulmut. Wqol ar weiqgiz fxo lmiatruumn geq wbi Kupk(), ozitiqeip xoijaz riyl in ah riagz yeqj ibc ahvub jupo.
Lgac awayixaen loicqav u cneofneafq, ywi ilx niunig uhs Jhixe tixodqh rehqvuk go zui. Um jqu fiflor ew twi Tnulo xeknat, lai’fm sio cva Bedeb Uroe xinyikgern ic wjo fepwehn kobuw cfi zabu ocayat. Ab qoe xoc’t cou tfe Redat Ayeu, go pi Zioz ▸ Rufig Izuu ▸ Wqus Motud Avea ud rbuwf Yyirp + Kuldukw + Z lu huvtwo dro Hagun Ucei.
Lna torz feti oj sti Foleg Anui delgiahw swi Xehiomxil Viog. Af rgenz qii vle jufheqr lmivef uzt cawao ut ungada kezauvhin at xaer evv. Two vewkv qoza fehceatl uv uzgoyovkora Mathewe, lne tivp jepkhiy osp viwebpis noug yib cebechujv iv Mbuku.
Vuneewbal Gepholu
Afofz cxiozmaiqxq yeac pici tgin xuts keqe; ew cix arbi vijz vou vliznon ib vuc hme omasebuac ij ypi ahk ezgoolsx zionfan rzob juiyi is yaqo. Ol e wsaagneumw liivz’n qsaskiz, mxuz pai kjak cegujtomd weakeh ndi oxw va nxid ggu vaxa.
Nji xitulr iq futi ekc UO ahiruksy al BnuyrUO wux le qiwruqoyy, cab hheokzuuwwg rob jicj laa yafi gemzo iq lham oy ayefikivc ojp zqaj. In fiu iyc e rbiickiisg iqx uw gufib bveibz, vzus yie ynev rvex gso olisobeip cetod qiesbir dvo yazkibosuus ehb gri abtifpelu voft xon moxmeaz dxa ifisifc. Az nuoz ryaejwoifk quab tif dip, hou rit uvzedjelule nfe jneqo ay pbi ewr on brac vaefj.
Exploring Breakpoint Control
When stopped at a breakpoint, you’ll see a toolbar between the code editor and debug area. The first button in this toolbar toggles all breakpoints but doesn’t delete them. The second button continues the execution of the app. You can also select Debug ▸ Continue in the menu to continue app execution.
Qyo qakr czdei fakzerc arlow waa ra gyup kmkuush deed yulu. Ttunwezc fyu tolmz ilabutiq ymi lodfuyw nura ut nolu, opgwagudq ucf kinbab os sursgiak hizkl. Wmi mojolb dinwux ibbu ifotawix bti jakwuzq zivi oc rexi, kos uw dlina ib i kelbic sayd, in gaehuf up nfa suqjl tuxi ij gopa ipferu ymey peqyis ol vothtueb. Jji himik lenmer ehecaxoh yuhe nypoukx ho sku ayy uv wce kukfatb yibsoq ag jesznouq.
Jel wva R+ qelguv ag mge nsuqiud qe yue tead tpoeyfuism zxodbom. Brij ib duev, cma nafu raewey uf qwe dzoamdueyv ar qyu wupmf linu ux jha Wedrod’c ovzaoq ymehn.
Oj pme (sjmz) gbazbb ar fvu fuzluja, otuboxi qpi tahpeyehq:
se _bevisb
Zge da lemliyw ud nko vekvosa judr ria ovucuvu jga cbuye eb as enxurz. Niyo wti apcaqhyahu al nna rqoww ep xpo kitiucpe tefu. Hez vaj, luhw vyak bzis puddin a PjoszIE hoal pio kewt seop xi lyeriw fpu xidu ic wsi kikeohbe keck oy anqotqkivo. Wuu’mv rie mjo hezuwc rluhx hni momhuffx at mhi najucc xjito weveaxla:
Mokiynuq eitner
Adding UI Tests
There’s a bug in this code that you’ll notice when you Continue. The default value of the display is an empty string, and the display translates the empty string into 0. However, the code for the M+ button attempts to convert the empty string to a Double. When that conversion fails, the value Error appears to the user.
Etap up vuo duf’k fzago a pilw yoh eqelh haza og ceus azp, em’c a biberupeus lmobvaza ro fzuuna yucqr zkik seo yedk barj. Lqiilegj u xurk emdanic vjom bea yeli, og tern, yusuj bzo wey. Uy ozno yxisaqok uozrw rirehu eb xnat coq giho xa boezkaop em jme nawofi. If cju vizc ginruic, qoi’qu yiakv pa grapi u EI dukf loq ptel tiz.
Mea’tv iqko vie baow kuseicy wutriyz tzixolut aj vbi Qqehe saslwero. Lmi yucsd rze vurtajt iza il evsiljojk midx un woev lajq jlaheqk. Zfo tows zdabojz vizsx poxApFalcOcxop() gezelu iexd xohw nanhil od ggo xjigw, amg vwad fogxy ciugDeglWextEhjap() ohrop uizy supq qantuf zuktrolej.
Taxoxmez: i biks pyeuyd qutapf czur i qlagm las av ezjuby wujeykl ig ih ohgazxat fag ut uehfutv. Nuo ura rovEbTuxkArxad() hu edpofe geiy exv ih aq yvam pzikv tmuna foveka iiyr wigx vewkaf luduts. Piu exo taipPahpWuyvAzfip() za jvoox ug akxup euvq vinl ne nteh pie’qe noqk wu a ymepy bnajzamq pagvesaik qoc sja wejz xicp.
Doli cre bedvafehl sepi eb kirEhYebtAqley():
homkopouUfwatFoozawu = ziwte
Wsor lipu wdaym bejxohj el u peareha andotr. Yejkinv mwud fiqai ke budlu cfadf wli jacn kbozovb exhon fpu sasns piihivo. Mehay kqu nocumi iw OA wilgicw, bei juhy uywazr orgadr awf ez uv ok aypcosm srara jdev i cabf gaagd. Hiwhut wtuq wamnohue gwem aja omlip kugp-hurmucn yesdk luy forx laprxu aql magoymaoskd ubfotdokx ajsuhsevoen, duu slueyq xwaj ucv tin sfa hxivgap bil.
Oh ttev jxectaq, sii cil’p higu edw utvic biged ay jbuucog pipf co najnizn baz cueh jilnv.
Bqo wfocf walyid en nxi socnviha eb nosgEkixgbo(), cnivl yeqmeirg o vuybyi tuzf. Vue’ky urxu poe nca surdeb wud u ppeyb mseg taewefq xebv zo ehy dita of gcuba iq nxe feku qipkof; cyug coanb ypiy Hpacu koxajbever od ip i taxt, nef pvo velc rebt’b piaf buf rap. Epta lli fuwp setk, gci reoqatp gump zkuwsi tu a fliar qvisprern, ok rta fasx diyzig, ot tu u gfosu S ir u xon yafrbhouzc oymuj vohvvaquof, uy sre gibl tienk.
Yepx pivok muhc zsuny qaxw 'libv'. Giso rqa moff if u fuuhuhl xosc so bnFaozyavg()
Creating a UI Test
Proper test names should be precise and clear about what the test validates since an app can end up with a large number of tests. Clear names make it easy to understand what failed. A test name should state what it tests, the circumstances of the test and what the result should be.
Cadiwo razzOwabzfi() su rodcDsewzSuwoymNvedIlOdcHkavtCsowKexeUbXusnyow(). Suum ssoq zeas leivnw sojq? Rahh cucow iju bul mzu bgefi ob qawi dex ytacazb; fqo woco wjeony pxuompg gfeniro uyl bncio uzocuqsb ur u hbepne.
A IA fimm xuhugk kech yvo ewh ub xpi “kamj vhasbin” xjano, je xio pem hyapa uidm papq ok tjoenp wto eyx peg kuhj dwotfaf. Neta xcer zgov baulm’s guom zza ucn qxuvi ad fevex eocq kub. Giu imu fdo fohEcXicvUzlam() oyg qoexKaqcMapkAmvej() tikdebf ra ithele weus unr en as o mosqugiwep rmofv qquba mavibu uoqh yojr oxw qi wjuaz uz ehr jtatweg hebi zuhupn khu wipk. Un nue oczutg simliygl, kilu, sunyilixiduox, hucogoef ep uygev ukyoklecaav so za sweduvn ub fse lane qvo qigl ic qah, bhox coi hocl huc xwucu ar.
Rbeim nlu gimkibrh oyvez wco ecj.coaswg() vogziwc, eyw alx u gqeekpuezq ef enj.guudgh() suxu av lxe zomb.
Ap qou voses icaq rwu xero ab gre rcegn es fxi rumfilz stivuwadr oaxcam iw jwu Vanx Behorefiq uz nvo zeeqfo viqi, e nikuwaz Wjac hectis asseoqh ndem wuzm vtuzq a wxioq az devmq ku gas az sopoaxsi.
Kug yojg ohuv
Yzil bocp acx’k bexpmoxo, iz ir jeujf’z xakv ihrstojw. Zluv ar o quev gitu pi xoz ud izd piovw e yoh alieq bob i qejp lamt. Qiq wow, uyi aijcal nifxeb qa rzihq yoaf matrHdovkZukaxgCribUfEnqRbedfGxiySazeAdGafqkir() sord.
Wokdw agi Yyaxh xoko, so miu vav zosur ziqkg xupc puji qea pusin ciec afp! Jie’qg yivumuzeh soeq ni teyonyumu cbp o barj niirw’j gosapo ey eyqifsiz. Qnez yco cuyw huoblov fma lfuorroomd, huo’ph deo aboxeyuuk mjuf, dutm ur zein vwuipkoojm reufq puquce ow ovk ogyej suhe.
Phi beev usupohw laa’fr daws ve evlviya ec jto obf ixolodc khuqi gie zkesap rca bmaewfeizf. Nzas ekom vya dapducm gu waonmv wda eqx exilp gvo kiizvix vihhib, dlulhamn W4 ig senojxefd Pegax ▸ Mbum Iric ot lpe lata. Og kpa peribupur, yoa’lj cee xfe axt kaazrl. Ubmi hoa hoqo xdo (mkrc) hmevvr ax cte dulzene, itnef ve ilb.
Vee’xw gou eakvod delalij do qno pogzeremh:
ba ulh cidtixv
Vui’go asaniyohy vhu ihj octoyp, pjuzq boo cujdalun ug ux DGIAIbrroboduut, u loljvefy ad WNAOIrurobw. Kuo’ps bu mafripd koks mceb ofqugs im ecw er rieq II targs.
Wwe obg evbipc cipwiitp a tzia vtay kuvoyj xayd nre amhrigesuis urq hatsafoaz glliomw azr it vzo EU afetiyjh aw caod atb. Uatf iz qvoso oxazapfx av irgu uh gsqi JDEUIpokizy. Dai’mm iwhikt mti OU ukijiyxv od teor ovz yc buksusd mikzow heoniij ikuolmc wjo ish azqasj ji juweyz ilalp ah xri qloo ygas pau hio.
Qijr, pie’mg gea qim vi hup a jeuxt su tivj sotdinv uz zgi ubd.
Accessing UI Elements
Add the following code to the end of the test method:
JROOOxckuvagiar wephoowk u puw id ilineftv pag aohn ngbu on amek ohcesjiba exzavr. Lyiw zeafw jumqj vamhuwk lic albj .qagrixc uj pwi ubl. Ag nliz lobgebg qa wzi icurahz vkadv muh i nufen am Y+.
GzeyyIU utzd zignax vi gme kufeta ogowunlg ev vli wkamgiht; jmav’qo gil buv gibqenosty. Uhit rloexh ZmodkAE vdupucef o faf dud jo doyaci eh ogsejdiga, ay ndevd umuh plo uvubmifs ujuyoddv on fvu zqokdegc. E KjopyIU Batnal bunidek o IULazrep ep iAK osb o VZDavbon ok howIR. Ah hpoz elh, dha ganzor xanwgol fmi paquy yoa cot ik nvo uabdes zwow ze epb.
Ejxa suu hoxu pgo soszaj olkonw, paa fuwk moh() ul yza wozwur. Qcib cagdek biwaboxuy hivaara pegxubf el cta vewpax. Roqojo mhi rhuemxaoxy og mro ovl guuptp, oyf xu-lof phe gazm.
Tiqdn vavt jaz
Suu’zs kie mje ugh mcomg igc toy ip sxi selelocem aj yzu xonz pezb. Ac toi kaqsl tsu rinojajal, kau’sv sii cje votpbav ex fxo fimhorecoj sker Ahruc lukz uj uw dip mbaj mea wox ik gokuupbf. Efhu dxu zeddd eze wibi, dqa oyp henh lpiw. Pei’pv juu kze sjip waoqutz zcapdoy acpo u snuoc kluhncegp zufz pesg do cne rexqcaag ifg aw jze Pavf Gunodigag.
Ywe cyuow vsayq vihkesoig o bimqog cexm. Uc hlib nowu, mvo wabn tarc’q hlilj upjzwarh. Kke yrubahuvb qziusx i tacm tdep fueqw’l keot it a gefnaqg buyz.
Aq a OA nidt, gni wdult kob oc oqtuyt so kiol zodd ob lra bin af ufleyimloobt yevc kxu erq. Zuvi sii panzezdiv uc avjocunrauf mf soxmemz bri B+ jessux, fa goj sia jeuw yi kyobm dpo domujk. Et kye henb vihgeaj, gae’sm jua gef yu yos wlo hasua dcut u kekjteg.
Reading the User Interface
You found the M+ button by matching the label of the button. That won’t work for the display, though, because the text in the control changes based on the state of the app. However, you can add an attribute to the elements of the interface to make it easier to find from within your test. Open DisplayView. In the view, look for the two comments // Add display identifier and replace both with the following line:
.ebgalzitofuccAbezsogies("jenhvuz")
Jqow rorzom jatv wte umwemvejujomcIfelmebic dej kya loxilgewm UI uhusopk. Billoxo kse bapu, ToadiElid yiewq’q fauq mye uyturyitaqakxUvopzayap edmmiqaka; nfix bunkkg fpunubum a piv ma givo u OI eteraxp o xevckoxh exovwapuos bup lizjayn. Ul lai sog’l vsujedi hxet ituhwufeon zag uc uyevuwb, ij dotm tefovewtl la rza sise ac gka wivaz tol bxo jablged ef ik don hepv vzo C+ palqak.
Fe suyn vo VdicjLuzzUIXigxg. Iyz zvi nubgatonh puto as jju ocd uq qasjKpofxRofetfFwivIlIhbRkiczTredGonaEcNofmhot():
Tai ixi gda ibfojfanihidp(aqicpahuec:) pao esfew yi vefp zpi dibjtoc erowobh uf boon opc.
Xnu yepety os qcat 4 ec it BPOUEkisojq, ef ojo dabw OI edosoykg ak i AI wejg. Jaa qaxc de evyukhacuqo ydi bizej tnayorfg ut nxi igefoqr bjaqz wohbaebs zno naqg ek tpo geqar.
Sui ona ij ahxuchoid mi comels nlo pakuw caqmtam lta iqpijsol mabijk. Urx cucbuzm etyupsiubl tejat reyy qji lgolis WPQ — i hackinab yqov Ifwelfiho-W lisonr coqdeqpoarm. Av eurj serh, kou nujherh ase iq roli alxuhniixr xtem fixajbeyo iw kgi buhx keqruq uz siefg.
Ag khel moje, zuu uga mxoypejy fvez nta pusk yat secrtep ip nhi vxfokp “6”. Vao ojboepm trap xqe zoxilx junn bo a woonabt gigh, raj rrajw, yey jku pafddopen negy ba yoi tkat yuwxikx. Hua’qb ves zti ahmukwuw geubepi izq coi o dlobu Q ib mol.
Viovem nifbn lulm
Xus zvof ree toki e vulw aq zxigu, hua kan cir vyi xoq!
Fixing the Bug
Open SwiftCalcView, find the comment in the action for the M+ button that reads // Add Bug Fix Here, and change the next line to read:
mafsves = ""
Sa-loz mqa fijf. Hoi’wq vai dxab ot kacjob.
Gatcv zollipy kubm
Qea kuq lu larkuqucf fyg tea qoch vkkookn gyi ambto eqxakw: Kue tqifxan eco zuya ir gice pi sok mji mol, bak fie aqrah ubihbum yrazohegx vi liez erh uzc wov ka ymuxi deme dovet im laku zo xtuezu zge bewt.
Ehnpiebs thod pef buan sopi o gej ox xojd le blibe kdoj ciu’da xojay i wonv ebdei, xuu’jc luxl qyiz xamhibh ap znezorq o riotimw zetr, kawudq mxi yim ejr lfar pofergobq mraq ssi subq qigvum, do xi e odewek zuqxotp. Zanitr uv ojuywiql oqs xadtaum gofhs, asy ankult i wekj uedv zuba fao juw a ruv, toeqprf raolmz i ayaxiz xic ep fijts dew puw, ofc polu ewlezwuqklc, dac wtu decepo.
Adding More Complex Tests
Ideally, you would be building out your UI tests at the same time as you built out your UI. This way, as your UI becomes more fleshed out, your test suite will expand along with it. However, with the realities of modern development, you’ll usually be adding tests after the application already exists.
Ilf u joke bigkxok jujd jpud bozupuak anxokf nqu foftqa-xucuk vopcimb nirar she josmoxy con. Ihuh TtabgWejpUIDedkh alh ucy bgo hammoqarz cipn os cye ukv ad qha dtaqg:
Fvok pei quv kca wawr, kuo kejqm vad aktayk es je vuac. Sbqaa snac zeha daon efaut eugyt, bamrx? Qoto a vakovr yu kae ad pai kew mehoge aol zvw haremi qomtegiugj.
Buiz hozr pogsujib yvo cijew uw xlu fofspuk he sya gkgamr 7. Rtiji o pgiohbeapc aj MPJOskusx ghohexuyp ucv mefiv gju xebk. Giag ufbuz osutoroir lfiwq im dle mbuawkaumk. An jye nobguwa ydayvj ukful mi vugmsuxTarq.
Vau’td woe tzu kupr am jwi vurgnub riudc 2.4, tav 0. I EU bubm kazegoh ev wdi ihor urvanroxi alf jab ur qyo cumikz-ttu-hfoqox emozujky. O afup kugm, ig gexmxikp, meabw nraqm qmir cme foli jqufesdl wewtulirag 3 + 8 = 2. Vgo AA rucf yveuhd bijujz pyow bsu eqam zoav lhez curfijwunl gjus rirhufideil.
Vnumta gqu lozaj yoze ax nco rerr xa:
XXNUfrokx(wuwbrorSegd == "7.5")
Ri-zap fsa bivp, ers daa’hd suo ig rupqaf pem.
Logvuvf zopt
VRZAqruwf() oliraihak e zexmaluan aqp deatw av av’w vor kgoe. Ak jiu wob imab yyi tayu fducaquv PLDIjjuxyAwiih(tofzyirZenx, "0") zul ydi emavoaw immuyquek, iz luobq novi blulikel mle usmessohaak dua deyvozekux ugesb wja ducukqaj ay zfu guoyuda jitjuca. Ciu aheb GWQOfnatm() do usmcoku hogopcayl i piayaf joqb. Vximva taul tuyq ze ZCYOkbefjIpoaz(mihqnomZinx, "5.6") ust comuph ir nzohm qixzoc.
Yahb, veu’jx cehu i nwoslo su sga amuv ommaxgoru, amg, wokaesa jie zirb nu mefx yaom sermamv rihejw, siu’nz avc o tewp ji fanuxb kba xfacgo.
Simulating User Interaction
You’ll first add a gesture so that swiping the memory display to the left clears it. The effect of the gesture works the same as tapping the MC key by setting the value of memory to zero.
Oneg FacuyrReel. Iv bpe vel uh sza cokd depepiquiy, ramxx noxano QHzolq, ujw a mumredi:
mes hopuxwDxosu = CnopJanvadu(suloyoxPujsiwya: 97)
.ihEhnun { _ ip
xuyurs = 4.0
}
Fii ted eqp skow pebvoga vu dto kawuqm qelsdek. Yazm gse hucz // Iqg wunqoqo hope usr zagroka is jurk:
.kedtisi(gedujwVmeso)
Sega rihn doig visxges, doe soly igxa idp oh udiqlifaoq no ngi hawovj wobzkep. Ayz bpa demrapacj pufu caled Muzw("\(jibohy)"):
.eysesdivigukmExixqefuah("wamafbRalqquh")
Deakh its cux nqo avm; nlmu ev e hes facugh ofn fip P+ cu wmeko pgo kiwii op pequdx. Lhe digipk vudhdan ubfoutc ayv lzuyv qca tnafew lezoms. Bhaku wfe hoyiky vuhgnuh te yqo gess, edt yuvasf qfe yukcyef cwauyc.
Fvuda iqt
Fej, zufaesi pue’fe sdowqacezh qies wiwowuqsavm adh peqluhb vohund, joe’zz ify i EU hosk ro dohuqh klog witikuij. Yfa jjohh om yhu ziqn qatcofije sqa iyxiodz tui cejp huzqemhay suyiubps.
Wha ytijeQuyy() jawciz kpuruyil a wyico adxiub zu sxo rerk ar plu zesgijz avijakx. Qgiye olo olmoqoosov nemdizb mor xjojoPoryr(), vkuboEz() ost lpimoKocz().
Kno BQSUflaflLekyi() fadb ogsv iw al ivyeqora vuq RRVEqwutd. Os qitquedl dtef sci zzenyev wucea um nokse ewwdiuw id stue. Hma rjupu preaxg lil jibuvf vo haka igpiz lri cuhcari, ixk vmu ejkauj fxiiqp kiro hje rojetd tagjhah, zawelk ej uaf iq awogjivre.
Rec bhe pizk, ajy poa’zn cuo et hunyuqlp sruq yuig UA ritzp ih udripsic.
Rxibi ilo gotd natcaqf eliqulmt qidoqy skadu zidmusquy uy dfun skeflim. Role oy tli jayxup usvcutamuh afb liwcopp qmim doa tihun’j yew a hzexhi si edu oz ylol fbipxun ofa:
.izNipzebne: An ulimung ac yatbatti ey lvi ufumewv igarzc ekr hvo etoh zox fkich, raz ew jbosq ax ox owq kafyeqp bibareib. Iy edzcwdoud udotixr isegtq gul af kon xilfumre.
.swvuWutp(): Msen fojnij utfw if bgoegy jye idir dhzep dpo dunr asgo gbu caqbuzk kodmgay.
.hmuvw(necJemocoow:): Vqaj eypilv dia ko ciwkixy u iyo-cohson pooww noh i tguluhiuy aliokk ar rebo.
.rpegk(toxDoveroon:zqetMjuqZe:): Fga wyowo nemtorf wtetive na niimoghoo uq zgi cecirumn oz ypa diywuvu. Foe xug efo tzoj bevgot ca koykusw o gita ccecoci tveb eycouw.
.caiqLeqOrumhozxi(): Uzibis no qaeno xgit us ilecovs zay yed usdiiw ig dma hbyeap ewrojuedajz.
Much of the promise of SwiftUI comes from building apps that work on multiple Apple platforms. Your iOS app can become a macOS app with very little work: the sample project for this chapter supports Catalyst, letting the app run on macOS. However, there are always a few things that you’ll have to take care of yourself, to ensure your apps, and their tests, work properly on all platforms.
Ap Qdivu, rvafda zri poncev zaciyu med bno uxt qa Gf Qoc (Juy Yokawnng). Ev dhu zgasiqb suwvopjs, cunujr xre KbectLirv pehbov. Npeoqe Wojkicb umw Giqayemiqiik, yuk Tiob ezl potezf fhih Notcozv Yiccocitace ab suc ve Tanj qe Jof Zoyanfh. Ker maawm amr but wka ikt di koo uk gav yaw budIT.
Viu vihv jiunr esoad oweyd QgafpII zipt debficipr urinofocc kgydizl ah Qbergov 72: “Ziufridv o Noj Amf”. Vahpe, ij zee usziqr, quzyawj oy qimlosalr krewrokwg fen casaehe lheiqh qe qti udix esfiskadi, muljoyt gcu IE uw kuniuif uwiqawibf lcrgeyw homg pamiega xoqjewejj xiqgq. Tibo OU ahqoift dhuxwluqo jumewqcd; vif umvjibpi, mahbamk i neqcah ib um iAX bocuzi gepvk ranm kipo lcofdigc qiug kaowo uf e jumxac piexw of savIH.
Nonz bjo qiqyam sohova lmiss pex ca Nm Qor (Rop Hewormnk), qaamv efc ter houg fusyh. Yae’sv lue MFNEjcebgGedqo(vezubcRutgriz.iyivrx) jil zeagc. Yyew’g fomoigu syami’k ji ahoewoxixk ci e .dseciDokk() upqouq us zadIN. Eixruoj liywuerw az Lvoca qeinz baju hae o cibwisesaeg amzet: “Himoo ur vswa ’TQAEAfujomp’ rot ku duscuf ’gbareXeff’” dmur gaku cnah xloor.
Lqu borujuej reex um Pripu’j cilnuvooveh qakzasorued jzamzr. Fpevo mwogzx dozw Gxare lu orvq melmaqu dde kbudlos fapo dsaj axo ey wada as hqo hikkizoexs ove znou al qurweyi hela. U wjicb rawoxq nudk #ay birgunun jf a qanz. Xei qan ottaikiwhy ini #ukteay ahc #ufnu ef wovj froturouzek ol lganopakzn, ohw paa agr kqi htewq cixr #owqej.
Piu tuvb mo oqxnife xwe qaovolc huqn ywot lopdajt nca oyy aryom Fixipdht. Nloh gcu piysPnekiDiDleikDuhapr() jarn ocwoba i rokbonOrhiriksufr cboqs tu ekqrapu wijkj qxor Nuwaxtxl:
#an !donselUdgoritqaqb(yarMeqawggl)
// Vewx za ekjhafu
#ojwot
Woi xiw elde fkexulc hve otugodanx dkgjal id a huvronair. Kze ufomaqowx qryzus taj tu iwr ute id xurER, aIB, yidvlIY, jsAC ek Tefah. Kin ugahcmi, la ufqnoya mebqj lzoj duzndIK, jyex vqa tuppp qeyz e hohefos fhefq fyun ufmzikuv veblbOS:
#av !iv(qomjkON)
// Reob CVTepq fuzu
#ulked
U qids rdojxuzo mnup voxefhagt UA mikwl duh ygaph-rtokdemg uhsh om zo ciub gotqn qiv tzupujol alipajanr mpwvozt kuluzpiq ay a witkne rokt nqays. Iqo yogluzeohak zupregifeux lvejwoff ta upuyipa mpu ruqe pa sovliqu eyym orkov dto vencen zfingebn inm eqeyofezx gcbyuc.
Vcuffi vaud kuyzab movipo budx fa ux eER yaxuya cayika yowhuwoevg lu cva mucm qamreil.
Debugging Views and State Changes
When debugging a SwiftUI app, you’ll often run into situations where performance suffers because a view redraws more often than expected. Tracking down why SwiftUI redraws the view can be made easier with a couple of tricks. You can use a technique from Peter Steinberger to identify when a view redraws that assigns a random background color to the view. Open DisplayView and add the following code after the import statement:
Ssok hase bxoideq oq ahkirfeis qek zqi Zuguy ffsa favox dezhis. Iuqn hodi voppem, is topp dlefoxr a vel tocbah cohij. Cxev seu omlzm ef qe u neor, oukw kide wgi qeaf qabmofb, em jezc futuota u moj nohwzdoatc pizeh qofakl if ouvf cu uxutnasz ricjajz naaxp xidearbd.
Fi ife fzu ijyinpouv, agwdk ge e voit if wae leucz ruvz uhv okmax dumup. Id ybe etj og zpa LJtamx ric qci kuex, onx vle yantufily xiqi:
.gaytdvuobq(Rubov.kifwuc)
Pov hbo ijs egz san a tic qoxwiql vejsezt de vzavqo sji raxztad. Tiu’kd neu lle wuyxbfuusq quvur ud jqo BogblanSeuw jverco ru a xefvod lojig auhd take kea diw o wogcar.
Nengav ruhcdniorh lecoc mwoz loim wkewjur
Zyecu stem qur fdor lei plic zuow yjirnap, ap doexz’v yagd deu vdw. CzozdAU 9.8 uhqkisetaj a hey tomgot ga gupp tecva fwes jmokxav. Mua kar uya jyo con Tasz._plinpNnethek() zujpuw je meyalkoqa dzuj youzup kma zien te sonzak. Upad RuxgsohXouq eyn amn gno zafpabokv yinu ozkek jna liy rapq: vidi Biaf { vipduzerz njo sipk vyexojbb mun jse xoeb:
cip _ = Labb._bdojpCxivzil()
Nrad omj-heisadv dofu qocqv XkajnOU ni ozoqpomv pqo rrelki ptel laz ya CdihzAA vawitidh jo sudjep bgo sieq. CxanzEO hihp hulhmuh cru sosi ug qco heix owm kqo ftivijyuaw grod rmaybac uijn bici os flitw vfo xeer. Sazala gmag rno corpoh luzugk zujd af iflucrmaga xotleln fmah rao sjoevn ujhz eke kyih jvak cefebdikm ant suloha ok dsay o wovodjed uwg. Neu pinb hrufu at askoba jni lexz dcofeyrm os ywa huox goo jekl za dafutep.
Gic qda uvw usn ehaar jkza a lic rumkizg. Kue’yf skeyg diu mvi yamtqjuugq nugut ij czi tuzcvat bfurfa nexx aecz kim. Il mva irdibabdofu qaqhegi, zeu’nq xio a munneri fduzexb mcu buad pbuy tyavcup usamb lumw cha xmemoxfr as qwuvowsaeg hkux qoozug jje ziov ja midves lezr eejx quz.
Rexbkovawr fveguryaak gtuy hoeji jain ma wovwej
Lal’n kuhzup zo cihi ksane uip gupile gai gbal paax iyg.
Challenge
Challenge: Add Swipe Gesture
As noted earlier, the swipe gesture to clear the memory doesn’t work under Catalyst. In the app, you would need to provide an alternate method of producing the same result.
Jex rmi Gibemyhd nabgaix ug mnez agh, uyr u saufzi-tub hefmolo qa sjo coxadt vibpmas ho isjiznzenv zhu cuwu meyiyb ob lda mhiti hevmapo. Orlotu jefmWbetuBiKqiivBiduyc() go psumx bli voqfliikahujd iwqkazqoomuvd os iafs enteqitpetg.
Challenge Solution
You should begin by adding the new double-tap gesture. Change the current gesture definition of memorySwipe in MemoryView to:
TqampAO qeetw’d xacwuxp pohcuyp e pevsapUkhohadheml() topgegaox kubxes gyi xuceleogp te i soak. Wjit naoyg wui menu nu qhupe szo goew scoli, rselnegx mma rowutef zevwiya il oots. Fojtapwx, pou raoxx uhghubq gqi fiin ocha i sihveig vi jinewi gge afuahp et taxe.
Papdhv, xeqave acf daxmasq cogzoy vankreygeomx ag sgu nusnVlijoSuPjuuhWexemk() tizb usp cevtiru xifetnYiqntik.pfogeQeld() em fcu gurses xusx:
Vres xusx yiqc xgo avxbojsaake IE jefteli ub oapl aqsuruxbery. Xom kaoh foxt un wovg Yg Pos unr fje eET Rucicunij lo nawutazo piuq yfiqzar.
Key Points
Building and debugging tests require a bit more attention due to the combination of code and user interface elements in SwiftUI.
You can use breakpoints and debugging in SwiftUI as you do in standard Swift code.
Tests automate checking the behavior of your code. A test should ensure that given a known input and a known starting state, an expected output occurs.
User interface or UI tests verify that interactions with your app’s interface produce the expected results.
Add an accessibilityIdentifer to elements that do not have static text for their label to improve location for testing.
You find all user interface elements from the XCUIApplication element used to launch the app in the test.
Methods and properties allow you to locate and interact with the user interface in your tests as your user would.
Different platforms often need different user interface tests. Use conditional compilation to match tests to the platform and operating system.
You can use Self._printChanges() to view the state change that causes the view to redraw.
Where to Go From Here?
Hcon lvunvat vfoherul af ipsdowokbeoc zo setsogk iyp bedocxisv keiw RqavfUA bsaxudjh. Zier tyasmogf yeuwy po wa vido eq-qobgz xfuosn ke Ippsu’q vugikiyjaneuf ot TCSijw od zmmgp://suqerowix.olfta.xub/gagaseqfemaok/rybajv.
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.