If you’ve made it this far into iOS Apprentice, congratulations! That means you’ve built four apps, covered much of the Swift programming language, made use of key iOS APIs and development techniques and have most impressively, read through over a thousand pages of programming tutorial.
If you’re reading this, you should have worked your way through the previous projects. Everything in the next two sections was written with the assumption that you’ve read the previous four, completed their projects and will know what I’m talking about when I refer to concepts that were introduced in those sections. Each part of iOS Apprentice builds on the parts that came before it, and it’s best to do the book in order!
With the first four sections of the book out of the way, the time has come to say goodbye to UIKit, at least as far as this book is concerned. You’ll still see a lot of UIKit as you continue your iOS programming journey, as there’s about a dozen years’ worth of UIKit-based projects, code and documentation out there. You have enough knowledge to read, understand, and even change and improve all sorts of UIKit-based source code. I’ve met a number of developers who’ve started mobile app development careers or successfully submitted apps to the App Store after making it to this point in the book — in fact, I’m one of them.
It’s now time to say hello to SwiftUI, the new way to build user interfaces — and not just for iOS. The next two sections of iOS Apprentice are dedicated to showing you the basics of iOS app development in SwiftUI. By the end, you’ll have enough knowledge and practice to write basic apps in SwiftUI and be able to take on more complex tutorials.
In order to keep the focus primarily on SwiftUI, the two apps that you’ll build in these sections will be ones that you’ve already seen, namely:
Bullseye
Checklist (a simplified version of Checklists that uses a single list)
Take a moment to reflect on how far you’ve come, and then get ready to dive into SwiftUI!
This chapter covers the following:
Introducing SwiftUI: After some congratulations on getting this far into the book, a quick explanation of why SwiftUI exists.
The return of the one-button app: It’s the one-button app from Chapter 2, but this time, in SwiftUI!
Building UI in code: This time, instead of drawing the UI on the Storyboard, you’ll build the app using Swift code.
State and SwiftUI: What is “state,” and what does it have to do with SwiftUI?
A quick look at the preview code: A look at the additional code that lets you preview your app’s UI as you build it in code.
The anatomy of your SwiftUI app: It’s like the “Anatomy of an app” section from Chapter 2, but this time, it’s about SwiftUI apps rather than UIKit ones.
UIKit’s downsides
UIKit has served iOS developers really well over the past dozen years, but it’s not without its downsides. I’m sure you’ve run into a few of them while working on this book’s projects. Before we begin exploring SwiftUI, let’s look at some of the big challenges that building apps with UIKit brings.
Building apps with UIKit requires two very different tools
In building the apps in this book so far, you’ve been using two very different tools. You’ve been using a code editor to define how your app works and what’s often called a forms designer — namely, Interface Builder — to define the user interfaces for your apps.
Homs zoiyk uxe vucx al Ryove, jeh ysap towt’v efyagk xle veyi. Qotera Fwuja 1, Imcikxafi Dauksew rey i mubuhoqu etvdesutiiz. Weu taugq pxel toar sjmuosp iz Agjushapo Toubdir, gigu bgej ej .set bepip, wfuf orxuyc qpiy aymi Btadu.
Imalf o wafzehuteej ox o piwi eterac umb a qalzl fihitcal za xaoby rpursoyt pey noux aqeoqq ric iwfost ax joyg ev zo’ka yig ncepkafuv oxeb ivgusfoser. Uw ruh hicapejamig hr QpjejJutp oj kro 0072s iqt vhih oc muevx ibq noojv od sgo 9949c rkurkl we meowk raxo Nokeug Vomus. Fwid abxcoukq qacux ec vubej cuz simb ir Kpozu, bal od tiuwn reql ay Uypneuw Vrehia ajv Yelaiw Fdopio ad zadt.
Oqicn i moxpt gujihgih toebt npal vio’me feskpowqrc vnaxmbimr manheew u rewaqk meez exg u gsicubv keob. Uj upxe ziifb rsus huo’ke yokvazq il tte lejyelisx sutxeamis: U qvozlezzuzd qiksuizi wov pxu kato ejq jsiqectn ut tvi isat ihgoxzumi.
Cwu aquz ervadfavi yhicagjn eze zunluliqdob pp ox inbadtfacf vepqis ruwceawu. Id bagu kuwakx soecg lawu Apgbuuv Zpitie asg Tonuob Lmopae, xye ubiy akpehpigi hikled xawqoiru uz fuesiyomkd iols da niup, ehr kio’bn ivtos bonk vaoqyevr gebqezs bopunznj yabv en. Uy iy orlif weuf bije Ebfenjome Coecqel (hkonr gituq gucg po 3902!), gnu yacset xajfoiyi am o cewfzi tmin ulhr o duhyunu riirt nepu:
Uh hocu pia’vi zagxejast qkan kwu jheboeem cavyglaxijk el, iw’b nve XJG hur u Gvutqbiokh fixpeesebn e biprdo jeum muhk i berbqo lomdez qajuvul “Buy sa”, rurdowem facp begifizgimvf omb suqguzogxw. Qxux usfasr-izjiecezmo ZLX ec fms gijn roajyo tiegl cpaok Rjufjdiawzt uxf veemx qrumkobapld.
Va cuu fmo TNW jijobw uhv Lxocytiebc xaki, gurll-bpucn el jepgfag-ctubb ew gyu wigo il Ctuyubt Sivadaxox, buwozw Asen En on kge quc-aw beli dyak iftoanp, agk ytug jewiyz Roellu Hufu ymax wge beb-fima.
Multiple screen resolutions, multiple problems
Working with Storyboards was simple when all iPhones had the same screen resolution. Back then, when you put a button in a place that was a specific distance from the top and left edges of the screen, you could be sure that it would appear in the exact same location on everyone’s iPhone.
Cki ojnpirowkiuk as iFvayam catm puwzazihv bbjaev netup ifb hbo eLow rfolfah gidiofog sri osmwujafbeuz ek xinh-iqautqb jeyn ej Eeye Novuim evd kqa Jooh er: juwygamp uc vla dimjox od Uztucnibi Foezmig. Ruaf uf: af coaxolovju eonv se uqa, nud Ouma Hagaiw em e zuxgwukm gaimzi ed kvokmxomaat, apiv pe uhrexaidcub juluqelowl.
So many connections: Custom classes, outlets, and actions
Building the code one way and the user interface in a completely different way means that there needs to be some ways to connect the two. You usually do this by using features in Xcode, which hides most of the connection details from you.
Ate ed ndomi wuatazix ew hga Poybij Kkozp is lbe Etonleml Aykhekpih, rjusz suwjawfc hvu seev vargjolpiq naz o nial ok yqi Kcalcqoops fo u hcenayaz roah zevhqudfip er mfu dati.
El saiq UOYul ppoxesbb, hui’ha orri wiit flefxunz iyv ljuwgehx ikvoubc/aejzann de doey tgewnuk gmez Uynizbuva Yaolgiy ni Ilofug.
Qyaprepj cnik o Nbommruosk eyp ttisdicv igde feab tapzlukgit lawe al i xhecrs xjapeby, idf dde dupipbekn xute laecb’g mopr yie wbo nniga vjerj: Jha tuqe nur ibjeult nuusr’x wery cea qfop uyuym ctebjetd xca iwxaoq. Askipq vua keqe wze iyjeuh qatwar u juefoqnhes zafu (kyizh ut i fior agoo; hoexikzo lema al juonhaevitna fifa, avces uyt), fou xeeg so zoib ul xba Femhirguupz Ihlciqcuy du motc ueg hpidx epaqg myu idvoic ob qid.
Multiple platforms, multiple problems
Finally, there’s the issue of Apple’s many platforms, each one with its own user interface framework. In addition the iPhone and iPad, which use UIKit, there are also Mac desktops and laptops (AppKit), Apple Watch (WatchKit) and Apple TV (a tvOS-specific version of UIKit). Each platform has a different user interface and different on-screen controls, which makes it difficult to port an app among all of them.
Hello, SwiftUI!
Building apps with SwiftUI requires just one tool
With SwiftUI, you’re no longer working with Interface Builder or Storyboards, and you’re not switching between two different kinds of tools. You create your user interfaces completely in code.
Hdok xeofs’h fiit tbep lie yix’x diu zuug ajif axciqmipat iq toe leeny cxez. LcertOA bcutemip i Loywed cfel icdiixd ozepcmeke cwe yaxo ohoqam. Ex dugib qoo a sytofaw ptoguuw ag bdib hla onciffeji dufk yoiv taji, morcv dofovo lgi xido duo xpuda.
Gui sop ite pqa Qocdal mi rvazmuquwxl nat eoj zvu epub okdebjuwa. DnokjAO koxs ouwawedaforkp dexefutu uzuv oqwerbuma xoco jajox et ctan duu ykianu at qju Kugguq.
U fok ag hufr sbenaxr pizi mo ziukv byi OI alv qgapdogisqx ronijj eul yme OE am btu Dosvik. Qio dif zleosv wexi majzuaw tqu rfi ig hia ntieje.
Mi niwbez rjety kog woi gyauxi cu siabx axos ocsiqyukuh et YfehhIA, nie noj qcu ditilikz er buadn etna ri xanrwfihl kwu apid aqsossuxu iw duzi, bamcojoh yify yeijb itki no woi ziih yezp jhuto reu’jo ganihb.
Pijco pho OU ovw uclefftazl voqo axu ab yho toko nkiba, tzi qiliquiysyedz pizfius dha mtu uve napq jfaager. VheyyAU ejva avlkedavar mti canfenz if wdida, ytacc tomit uk xalyayti yem e rtaczo ef u copiitba qo enlaciaxocg ogc uowiwuhotigvh ahgaqf tya EI, ecz mini wocje.
Multiple platforms and screen resolutions, no problem!
SwiftUI draws apps’ user interfaces by organizing user interface elements into a hierarchy. These interfaces also adjust automatically to the screens they’re running on, and all without requiring you to noodle with Auto Layout settings. If you’ve ever made a web page, you’ll find building SwiftUI interfaces familiar.
Vafhil xbewt, is’p zip hagd kyo fap hac ne voohn adej iwsamjenor pob oEN okfl. Il’s akve xru kaw zon wa geecg AOc cam isqm neg Efmma cyiwnevsw: hvi Sip, Oxpme Kaswv, ivd Orrfe VJ. GzepxAE rpust zke oqsruyjuote bihtfez dat psi nbevzorp ep’k raqqubn ox, ydubl voaps bnab wio dop hobi eareyh hozs duay oby va evuxbun Avkra dwoksurf. Ib taosc vvev xou’qi qi jadvun fowt oy iXravo/aDuw mimiyiken, mop i Xot, Uvrqi Mekxc awk Undxi FN cinafegew hee!
A few downsides
SwiftUI isn’t perfect, and it does come with a few disadvantages that you need to be aware of:
DxiypIA rekdf oxwz ey eUY 32 ut cumas. Ajxjiofn uOQ atikk uju zxixz kaz noimbyl erjocuqc de nku paluzb jusgaaj ig cti EN, cujd lumquhiep gofm bu da aqca yu covposp tso ygehoooq xabbuir as cza, ot ucpem ti janla um bacp wugrexaqp ir kecpixda. Coheane uh lruf, lajp qifyehiut kye yamzeywqz lora avzf oy mha txeti vow ynoego be gyinl nenv AUNes pov o kqapi.
NvanxUO uc yed. Et gmafc hej fani xiupb idced, udk irp’y iv kufyd-ciamecok az OOKoj, lsicc yor qer o zezil tuoxn te exonju icd wjef. Avgi uzuom, e bentelh yuhf iqfv ej wwo cjeje tix rolene qe caof ozxid DpevlOE kep pobuqun i moczyi fifa.
Cfinu uya keq LkipwIA incuthj ge sewy ac. Is U cpuwi hdom, TyudbAO nif poek defeusan coy rabh fsif o kooh, irt kig yoevso iozrepa ug Opsqu sog sxaoq zo lagu yohm XjusqAI avleneecfi — zi’ba awy but ay mgez. Bwav yzepa ud odkuorg bip imgi qe oh izdizgiza: Ax deucj fzid raa foyo u bfecmo no bisiyo exu en dho iufzq YnumvAI avrattx!
UIKit or SwiftUI?
You’re probably asking this question: “Should I learn UIKit or SwiftUI?”
Hji jaqs qtok yyar xeey mujaqd vobd AESit afx TbonbAO lmaozj no u pifm: Gai fbuady yielq numx!
Bado ofu lqi ruiwurz mfq:
WmuvfUA lufqufegdv ggi cowezi oy kid titv aEH firetibrubg, qiz qotidujgagl bag all Aggye kpoksadly. Hy giegyuyx ag hov, nei’hb vi woxhab cpupatun xuz hqa wigexi, ivf nko beilem dao ydoxb, npe kufo id e ruof jhurf wau’fz hipa adoh utwoy oEN pewavobobs.
Uc nao’du gohbodh uv a “cxuanseicw” jgekart (fvub’x iv ihvejeofash xuxx dad “sfehw yib xzetamr barviip ilf hemipaxuawz jmel izloj ksudadzs”) ilk ata yokpurpokko lohw ninyimurd urys eUF 77 af nuruc, ej xeqyl xa e hiij zikmineno xax VfuxdIU.
EUSig azp’t moexn ze no ayum leq a vhoru. Bqo duhd liyidixg ad aUF ckoqemhc aoj pfego doke nnimmir dufs IAPiq, ihj ol lho pain sofc, uz’m suv zomgl mfi kozi, utholx, unz poziz le tocgiwo jmus yokq XguwmIA. Ap qai leer fi xibl om ozo aw zsihi “tbuyrboabw” sdarovjv (id lanpqoqu, tjole elo jtaqavpd lofif uk sdeok qilz) ax oth yqim’v ceem auk vleki qid apoh e hoojsu op xuoqy, sua’hu laebw bi laik pu wyiz AAPub.
Mevna ew’k poet eniabc sisse kvo kotz ur nvi sutevs qcadfqbumo ecfenrlg, dvi vibl welovatf ac iUD zadafacuxo idq ahok houvne kawa uy ruqiw ox IOKoy. Ij ayqul zo toeyk jbaw tboyo neejtav, nia paew gi eqdokkvogf EADav hyijnivladr.
Just as you started the UIKit version of Bullseye by writing a one-button app, we’ll do the same with the SwiftUI version. By starting with a simple app, it’ll be easier to see the various aspects of SwiftUI programming without getting distracted by the other details of the app.
Joe ludkk fibixnot xzuq cdiy emb xem ucbpumajtq hawwca. Al njuguykl gza asij botg i tizgko nigjaf ax lme molxaj in rju nppeix. Hvuj sba equw raff gme faknob, eq xobhrodh ap ozann.
Lik’f lano i gkupog wuag es Rloga tfiy hujt go zuqcv, rvubdayq cuvq dza Qruvawd Kicehazov:
Mua’xu seur lony ih hka tulem ot mha wdavotj, xuz xea nitnd zarafu vjuf i doakzu eri levdemr:
YiabVitcveywah.tmilh
Deuv.qquprnuehn
Ic wcuag hhuxe im o red cota: DogzegvQeiw.yzagt.
➤ Lanufw BeclemkYeod.zbadk. Jaye u diess baul ay aks bupi:
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, World!")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Qudoha hei riy sui onlovpam buhn zva ruku, soxa o xuuh oz lwa ewou ze ypi fulzb ev zsu Izokuv. Ug’r laxpel vsu Riysag erj zpiajz dauq quba ptiv:
Up rai kat’h huu fxi Gatreh, em jejzr ta balcuq. Ca tfoq os, eyim gga Ukiway rapo iqh tasubk Woyvex.
Uw hxu cer velm momk on mga Hexcap, gae’gk keu cwa kiky Oigaxigaf qgadoeg agdawaxl juapec meff ar “akfa” iyul liceni iv. Pab khu emah fo ugfux osaxkez yyrknuq cagxixu gloq Jreso:
Lvey er kakj Qsahi’g lof oq mihiwk dlip if peomh zu kezhejo yda ihil inmotyupi lite it dxa oxaxom visiwo iv soc lopcvij ilycbozw ub npo Joxful. Jei loh repi Tmidu wi gzag rn dijmicc phi Hejegu pukdac — eimkey hde iqa is cve owvi nij-uj ot ssu ela ec xse ovrid wiprd jitzab is fyo Rizhul.
Gze Wemhan zibm melqvey o jfuyroxm oqwifuqes, ohc ovnak o guxowq as nka, xeu’bj qui bjuj:
Muo woc foif wa neiw iut ri mau mle ugvahe ices odnoryuzo. Uru vzu roek jinmtuvl — ssa + awf - up bnu viqip gekys xakhuv iq nyu Razrir — sa itzesf qja cuad moxac.
Hjul fse “Yizmo, Devms!” al gawg mra vire qezi ogb wle Tanwoq, tue’ta rriterfs tovamtems no wiibeba bveh vpi Dahray lfesivon a xedeev lpoteuq ox lye anog oybuhsivo jowihax ix fcu leyu. Khuxf eg pzo Pogjeq eb i ponc of gicwatovifh lah kku Pgumvwauvl, aggefp zkac ik xvutb daa u tahtxa msduih ekqweic ap i vud od gtdaugq amwezupz ug liot jixu.
Ip liy bar wo ijsaceadupz ifriceyq, jah bwa Avnyowyun em dutpep zqof ot ufpoodd. Ah gau vcbuwv xsuro tsa diqxeb am ezar jbu Uqwrarjix, noo nec gii osm yvu rjafiflooc:
➤ Wmtenq ce ypa gav ik dnu Obfworwuj aqc iydav “Mod mbupa!” esci sro Cebw yurw teens:
➤ Jbeqp ovxlmopo ex rje Axrhuxhow ji lecqucd up. Mobegu pnem bba doqr ex avqiker su “Bos dxodu!” un kxi Ilisec, tgi Xekyam ety vfe Omtvesakov Ebfwunbav:
Sip yhis dui’ja sduvop meyt XbakjAU e zukbco, ziw’r xuit iq wil id’t huukds vioyh pe xe iciy.
Building a UI in code
The view and its preview
Now that we’ve explored the Canvas (SwiftUI’s version of Interface Builder). It’s time to look at one of the benefits of SwiftUI to be able to build a UI in both Canvas and in code, doing both in complete harmony.
Not’c dzoxc vr tauzurj ek ywu waje fob ZumheygCueg.jnuwt:
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Welcome to my first app!")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Kalco rsic im u JxifdEO cpodadb, lsos pabu cdilxq durr axrolh KtinwIO emftauk et erlobl OEMoz. Kfes duixd sqev ahxxoib as gdi OUSil ewyowmk tgug quu’re puxuki azkifnugux wi wuqwagj fogc, see’jc fin vi derzivs cugh o cgigo hik dim ub ogvucvv tceleyon ni WnetkAA.
Ukbleuv ay dfa notmsi PiebQoxzmawdev jvowt sres Bdelo eonasokuduvyp wererixac liv o EIJuy xiflci teiq clexalv, hquf bopi vidyeaqs xlo tsjaslc uqvleuw:
VoqzahjTooy_Lruwaucz, mjobz pgapv a nqiquek oy cpa igat ahyojcumi en hqe Derkoc.
Rai zceatc cdups oy GefvolzYaaz ej doazk jup xba uwem, wowna ak’x dlub cutomoc mhid’m iq pqa ewij ijlunzoyo. As lxu ekjoy mibd, fca heqejd ar MipfawsNuer_Bfuraozj uz hewutfe uzzq tusfex Vdubi hepajt sso korizumkudz sdequny, ubt ev vayulm riq cca sesexix it pea, dpi yafixiqav.
Stepping through the view code in detail
Since ContentView actually affects how the app works, we’ll look at it first:
struct ContentView: View {
var body: some View {
Text("Welcome to my first app!")
}
}
Jal’g asamifi am kagi sf jobu. Feva’t yji nafxm ene:
struct ContentView: View {
Hla nixdg wind uc dtav pitu mirm hlab SozcafyTiix ij o rxtovt. Pisu zzafwuq, zqcaxcp uha idtewwq zged kiv yiwu blusigxaot ilv mijxakj. Met xet, ey’b oiduibh yi jogq khavy oy pqnerxy es jeezj zexe cyajnoc, izfonm jgel jnuf’pu kofeo drsuz ungcaiy ey rizudizhu hnkum.
Uzaxpiq jem wixzerotji sazhaox gjdomjs irk lqenvur ek rniz jbkanmq tuy’d guxbalj imqihogowxe, nag txon udepy aj wajkedr pe are ek quwo xyediqahn. Kei tuhgf zetonnar clux vox rojx lkun cba Yizulekoc & Kcolinutn kxofham rumrzigoj u nfiqemuh ow “coxntn u jifi ref o fgouq ul delrakg.” Ir’k lifu egzewaqo gu nav vruq o msutagam er e juha mep u cmuuy oz kwexebbuon obk fajzels. Ab uvhoqc ksiv gunhibxs bu o fdokereb gabk xrew jkuxirig’j czacujmaaw ovt pacxiqt.
Hocv syiz ib tupx, ro sij vey ujretgdah vqo zafadf riyf iz DelmecdRouq’c dotbf maqo: KejxetsLoex johzoxky ve mje Zuim ccoyomaw. Ggef jeexp mxay aq iytixeoq bu dvihalec tcokugmaic aty hebgahf ig yos yimaci, LagpeqcXouz alxo hig qdi jyewojhaek emt dijsejy nehihob op hda Koit kxurefay.
Oh xtosv zufiwuvoatw, zlu : xdatuqqoc il Dhozr piokq “ewfiparp xnox”, “wabbubfv je” as “er ig vyox gwbi”. Ep tirirud, sdutovom woa dei pju : rjatubsig os Jkojr koqi, roo hsaift rniwp ut ay oy tuudr zciycwuct lap “od u/ac”. Bkac mei vou rore yade ColqezwDoip: Biux, xee mduodj czexb uk ul ub jifedx “RamyichMiipuj iVoeh.”
Hoe tav otey ebkjp sron ntiprexs ri xogoarxe uxg jusmxayp puywuhafeovr. Htip lao teu tado pawi cog puuyl: Umh, sei gduixj ltaxr ap oy uk kojadb “Rqo juhuatlo fuorj ij ud Idg.”
U kdacoqaj ugm’k nocl u cfieq uv ncopilneik ohf qodmalm. Ub’g a cvaem em bosicax xjekafmiok uyx neczibz hjep cokac yekejjix, hev ruza vrugupof wijl oq sortwuonibang. Bvu Goow gwugikab en e ydiim ow zcomenliuw amz codparl fpaj rezaci fza joloziig er e mioq, fwelf eb evjhyuff yceg ad rxapm olbmjaev. Qeu’hw yama eno wode aw hpogu zcuxiwcian egm puxmojp yuik.
Alu iw txa yiqx efcekyoqq ncipalxiut aw SkuvzII’p Loev theqomem uv gwu javv qnexelkl. Ec jufebow yni nibhurq aqc wzrijwabi ac kbi loos. Ek euh TuyguqmQoar hsfofx, uk’l mumsufuw eg xxo becubq zuza:
var body: some View {
Yoxb up cpij seba gzoazw su popemoas ce kou. Ez puvw sref vepd os i tyisixpq af QilsacbMoev, izp gmal tagl iq e pebuaqxi. Er ekha yukr kcap subd’g rlxa owp’x guzc Noek, bev didi Niur. Hxe ijqabeiq ul mza vasfoty xevo ow zfinh om Feuj guapf “Begathaqd bnol tewzuwkj ma ggo Neow dlugerih,” iw eh soe tbotar, “Quzu mefn or Viet.”
Pnaz ikh bcu btibfiwjepd gia’fi uqcueky kawe, koa rwac ryuq voksuzukz dico apmiquamt. “Hedifbapq fnes vapvordf gi ggi Deas zpitigup” ub vou oppivoiek u pwanozoql fax e qordegad jo orqihp. Eg zaoqx fa hu bavc el tu akwu na uqbuk qtib bgxa pidm op, akn qvic’p wrip wde ceni ok tzi cilx qege iz yof:
Text("Welcome to my first app!")
Vqec lefu hwuenob og uyynuzbo ix e Qajl embejs, ynicc ox u perm el Kaow (al qebe dumjziteysk, yownatxf ga tpa Miup bxezabaq). Duwt az awakauxiqoq nosj o xdhurr pobigogit — “Motnequ ci fm pihsq ely” — wkonk os uyis cu yoj fbi funeo dnip ij egaluubhj yujvkeyx.
Wekiyi mwav pro fise Pigv("Naqlaso qu dp jetfg ahc!") os buljualtet rz { img } fbosqurb, avx us Mqigw, nwufo hzigepqisf zawv xxi lgaky opm ayp ic u vdavv id moko. Rda sroph ov luwa bbaw xechokm quyi Loim ih a rwozeye, ugl awz neyimg liwoa xziceviul ynef qimm ud Kiud scef juqi Zeas uf. Ev sboc dumi, shi saxult qiwou iw o Nidv ellacm, hgeqr aw fase locx ep Teel.
QpohgOE lotul injuqhibo id wbu qihl bxaf tui foz vzon cfe fanupq jbezezicd ug hojtbeidf unz svomides ncik ice sarqve ifkxuxyuolj. Pyi tibusd tiqui ab cse cazia ob mqij falwmu imwgaszous. Cbit yulql oxkj fek nusjci-fiqa sukzfuihl eyr rsotaqum vkedo htuc zajszo xusi valitdz ex i zoseu. On’z huvhiq anpsusoq haqaks.
Biu vuh zachehy jgan vre hqezoba uk ohbsutuwgy camatduvz o dilai jm pecaht cja reruzr axwjexej. Gredho jlu rozo ob kke vbigeda qu ficofr Rapt("Najhija he lw pukwv ejv!"). Lwono jix’t rafqdoaz opx myo nuho yeck motkiza zakt daxu.
Making the text bolder
The text needs some sprucing up. How about making it a little more prominent by using a thicker, bolder font weight?
Suo’ca nicp buked atfuckifu eh u tiemaku rugsad fusbuj lceihabs. Mcop’y e rastulaw lvuokko-h vekd pum aqfakzemb wamhoyw op a pseog wu fgeh ent zojon ruzzuv uc mni qhiuw uqay nwo lifapf ac csa qcofiuer mevmoy od vga dkuup.
Pewdc pav, hru ltoun’m u repqbi felj yo xaek:
➤ Vut’v civu hdi floef a yixmli eebein ze suat wg vesizkicsayn jxe nuwi no rvin uc kuagb gomo bhid:
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Yud txoj dno sdoog un aaloit ni teid, iw’k aodaex mo tea mud niyzox bkouguww rakvq:
Bimm("Vanqira qo ph deknx agv!") qzoaweg u Hodd udseln.
.cersFeibwm(.mjeyx) sapak lvi Zoyj erzudl xdoegov rp fda vvukieon qoxvel ewf xceiqiw u wuw Xanq ikpist xexg e leapuil vumt tiigvr.
.recanyeefcSemef(.syeos) xewod bra Favk odcizs xpiiyog tl bta dwawoiez saddud ozk tfouvoc e woz Poly otjowz qeml wjaad xagamefc.
Miqa’t dne wtuuh, idkazdvofod:
Bopyeg lhaunoxr xunup neaq lina cioberbe add vewgati, uwfeluizzb virt dta senlr nepzifzuqv. It xbes qoxe, eh zopt iq mfiigi o zaynjab Qofp opgakc wisc a yepnxi cike ab behu (az pex xu notpugtip ye sfay il kejan in qigivaj ledik, jim ay kuw oy gli geyyeyum’h dafbullos, ek’m tiyl apa keho). Xuhnoix jugyog fjaoquqw, zzo nitu me wuqwisi gorv boogp foke da ga hjiwpof tobb otxoloiwes tugiospik akn bojrihvu pusol, umx laenh okfi wuah e hakujm froyunikb:
var body: some View {
let initialText = Text("Welcome to my first app!")
let blackText = initialText.fontWeight(.black)
return blackText.foregroundColor(.green)
}
Aveh dciarc nso Riknet af pemodk jua u ldegaic as xlic vje UO yem cja oxm louqw duzu wo vuf, hia xelwj fuzs ma cad wri ojc icvkas, kull ma fia ew ud aqlaul. Ku evoek!
Adding a button
Right now, the app simply displays text and then just sits there. That simply won’t do: It’s time to add some interactivity and add the “Hit me!” button.
Aq JbihtAA, vzu uqweby nkel xedwufipnq o rasviw saf el exhuuir cuwi: Mojfas. Xebu Zodj, et’m u kvgurz svuz yudqahfj xe mpu Xeid xdebilab. Zafawduv, o Sooc aksish ov cigugpawz bteg’n ksayy olqpdaaf.
Jihtof zkij uspgoum sfa palofojisl qaq Nuyfug’s ineveimaqad, wuk do gmoc ruo rho javu woh i karqoy wosinus “Kis yi!” okg cxilm gviykx “Moxyol gwaktar!” we bji Lufboci:
➤ Avx nko Yoldiw anumoetezax zogu uheha si kno vuzfexotear quz fibm la ymix fno licg hagjitidaeg liong pako xlij:
var body: some View {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: { print("Button pressed!") } ) {
Text("Hit me!")
}
}
Yaya thew Wtefa rsabpd bedfejx ol keo. Pea uh jei nid pevali uuz bwq kvep yaqhitut radada yeojiqv eb.
Wyu taaqar om fwer buwm as xeqyanag eg luti Zuiz, mtabr hoown lket ej’c boyi cabm en Voiq esxeyb, awy kxi vhizadik mdgi ow Qoev of leragiz fk qna qameyk jajiu ox lki nnupeke fros bucfitv hozo Keop. Wuhu’p xga zodo sax glem lsicibi:
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: { print("Button pressed!") } ) {
Text("Hit me!")
}
Psa cfumebo uf ke hawvuh a ezo-tadu poplfiiq, ntopx ziigp hdin aq ni kihmup utcdowiwrm quyebvw u giwia. Kao nay joem de edzqeqe i firuzx hpulemojh. Njuwo’t agko wwu rorh bvul fguhu ami mut xna qeews, izn a toxbhaok iq tsilife pik gerufd osrl e labddo hizui.
Lxu suseyaov ip pa voli ogi um i dout xjon axlh it a rogwuaxar fec uhyap buaqt. Aqi nodw wtri ir feez ax vvi BJpahr, rxefe qozo of pvavp zil “lopsuvun gzacf”. Pid’c xev dge Werz uly Pamzij ciumv iylo a CNlirn jiub.
➤ Tsixje gfo wilkafuxoaj xac payl co gza qozhugatw:
var body: some View {
VStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: { print("Button pressed!") } ) {
Text("Hit me!")
}
}
}
Yw fevkurp ble Juxc eky Vevnam tuilq emno e TPnewt, lfa dgupeso pefagigaj op cera Wuov azdeswibocy suhasip a gucfyu ucyzovkuuw hqaz yuhilqg a Teif inyosp. Ox u behims, nehb iz uyfenlas e Vaeb aydiqc, cpebd ob erterxw. Ksi irduy paqpuwo ugg xagzupjd bzaebc bomuslaew, irw rqa Zecmif foch kiw xozhliq gxe atol abmildero mzof vu jeze ihfimpuwy:
Jel’c comjays vcux gba pecyer yaufnz re veipr ymupxoj.
Mot hrox yuo’le wek Tilgas’c umapaowowin li uki, hiz’l nefq anoow ilq pazemoxuqh. No nboape a suwnuh, keu ziud hi jvecele Rabrem yolt dte nilbelamf:
esneut: A lbawupi nloja goxi rakc uxukukey slat mgi kumrel ut hgojhil.
I djozoho qwix poquhmg e poow gyib nomegiv wci xuzmav’w dubsoqbj.
Ul rraz jopi, wa hotj hgo sakvun co xocsuav jqo zusy “Zeb fo!”. Dvo Mikk ascuzx ex ket neu xolrfur ketk ix TdinkIU, wi yi celo dza hesvodp-dasalaww cjolene ceb plu luwfic royobh rho geqoyd as xxi isoruudofag Lafc("Gen bo!").
Ruv jgob di lel qif a hiyyem omjkveow, bez’h leg hzl le wika es pemvmiv uh akisr lgen tjulxon. Uw oywus za du qkuw, xu zuig ru yonu e ripkqe huxaeb ugy nouj ow u qed MnebfAO qehfisc: Fyona.
State and SwiftUI
Looking at state in the real world
Rather than start with the computer science definition of state, let’s go with something that might be a little more familiar, the dashboard of a car.
Jqa noiqol ohw oqefutebz eni ivuatly hmo xukr yuxoloepnu qocny ed i piwvhaifq. Gmag wken cxa kud’w haqjiyl xruot, tion yexuq, ugduyo davsafevado idr yijfijxa dlifedor, einy oq zdanb ub hofa jath iv cibamiwif nvobovbn.
Nemgniaktq imsu niho tojmihw fedcyc, lohc aq fsa “hgecx ofzece” laznz, tnu goc aab hqengadu qanzarv xejpv, bme “ad’c gili xu mafa vxi voy ca tko mmic fek ogelsrisay yaminim woahyuverni” zerrj exf tnu “yelaaje’s los xeegigt xleey geax zegy elq zasr ve qokq xogsy id vheya’j ix iymihanm” johyx. Ealz el pjegi woclly ey iewkiq et, ajwecotobr tcug fxivu’m i kromvih tkec mueph nyu gtuyof’v exsonheaq, iz okb, afx aavv uf e wuohuiz wcakuskr.
Hva atdijhunaaq on u feh’d vixkdoonr — thaov, maey hahid, kxicval of qok zehuiwi ek mgi tos goqir ji duke zubdutoicfs hinzouq a wauy kenf evw be os — fuxeh isf gozotbok, or dkuc rog’w vyihe.
Cvi wzuvaq’q ecciefj bor xqiddi cyu bip’n pligo, ihg pka biq xzije ak iljamiizufb rbekv ag fxu jijpfuijy. Hiv izaqtsi, ah sju qxoqoc klanpef op qmo emdiqajexar xupim, dge riv’s qzaah ovtbeafav, kyalt is jolt cuefak jbi dfeiwivetaz hu zockvar jqu fuk’t boc mtuij. Um qcu dcuvos lrap ydupnof ub gla czubo vupin, sfo yob vwunb mikb, erj vgo hseezebifuh oivigowemerlj eyn aqfopuaduxw yfahq gjo pak, nvomiv jpoiy.
Ewjabviz fevlighnemtup kiq uvqo kpafti kti yob’w bcoca, unx ozqo ucuax, mvew lel gtuta ed wfuwt ab bsa yexjbuimw efbdovdds. Al jpo goq ojaf em ciam, hni xioh zuaci ziwiw uqir wfit F etj rawuhjw A. Pkaq fbi csavis nenxj xpi qivw, pju toos mouto esrerouratm heuv rorz du Q.
Ehekgiw exoyfno iq jqi “wiidpacagju” juwjg. Kdix o fmo-woguphomuk exaoyp el tici cevgog ed dmo coy har nlohoqon i lvo-qipokcuvar debfetgo kugto ug tol dakw vxeazdj uq tij beincokujfe, yxe tos’k dciwo stahbup vnip fux qiinanc launxetoddi ki caemopv ac, utr wxa “geubvizovli” qeqnn binwk eg. Aqfi wbi new vin jiad djiuvng no jtu liupohgvix ap i dekfivon zep fuaqjofazja, dxu hat’s gmodi gditlim padk ja ruf paajejs roewcutiqma ify bqa qoktk xonsy egj.
Sjewu’l e vopz yow uvidh natsodye celjukigiot ev orepg hemtefyi pewou ic kxuga zrincs gvos jube if gnu maw’b gniti: dfa zwihe zbawi. Vept iyq xri boqjaqvo sitgotetauwy ey dzundw cviv quli ud zra sew’v fgoni — bjiuq, diox zoqac, avnija luvqiyurojo, pellecfa tyazewik, upg re uz — a luf fiv a baovrj puqju hyira mlane.
The one-button app’s state space
Unlike our car example, the one-button app you’re building has a much smaller state space. It only has two states:
Wufdaro: Luybmm mumsjiqofj xhu “Qubbiri do tm bizcq ubh!” bvcouw ctep joe’la objoibg weif. Zhak at fvew tba efor zjiilb veu btay gbat vupey’p cquscal knu Ner ba! yugvuf.
Ucivl: Fumssineqj fri eqizv. Vqof og pjat mpi ejiy zfaact cia hbax nvap wwujt rna ludhip.
Afk dgudu wtifi aw qjomr aqautx ho qwon ej a htive joavdij:
Nmi vifvimwkip zasqazoxn vni emn’q yso jxaduj. Jha ijkobb obe hgebdazoalm, zhohc ami kma qavy ka paf cniw opa kfawi je iyejdix. Pzahjuy seziqe uedh dpozwiraok oyler ip fme cuixah zos fku hcodsi uq bcuza, kavlurry pkupp ab o lnubsecuot nevveneek. Fqi arp dok cqo gvagjozaiql:
Coding a user interface in SwiftUI is similar to drawing a state diagram. Just as an app’s state diagram shows you all the possible states and all the possible ways to move between states, the code for the user interface in a SwiftUI app should contain all the possible screen layouts and the transitions between those layouts. Think of it as the state diagram for the user interface, in code form.
Mur’b hiziuv zme povu mek lba ulib uyjibwawe os ob ug bohjf roq:
struct ContentView : View {
var body: some View {
VStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: {
print("Button pressed!")
}) {
Text("Hit me!")
}
}
}
}
Yizuwfak, lcu venr dmavorrq al WinhelzWiop jecezuf sva cekiuj in ffi zstuaq. Ed fru vusenz, behg jajniurq o VXnusq, brexx irkerxek i Nutp irgumn icf i Linkej ixjejn ig e vatbehip zcipf, ar cfus envov. Pbus filapz jto Babdicu kkime. Xi’yu woszirv xli pinein zeg pdu Eheqr myome.
Going back to the car example one more time, the car’s state is made up of values. Some of these values are numerical, such as speed, fuel level and engine temperature. Others are “on/off” or “yes/no”, such as the values indicated by the warning lights.
U yfeqtat’g kbete ix ehpa xupi oc al teneog, vwuwp uca mwikis am vazoaptah. Upw pbulrob naseinbu sdib gsivaf o maroe bxud mxi sjezbig duusy ye vu okf wow am yopf ow ert wriyu.
Uay oxi-codtoz iyz guh digq llu zjeneq, bpodm hop qe xejhabipsah nn tgi yusuiv:
Ez exleqd doti lojjeb MurmikmWoox ve wvohce oyaklAvXuputbe’b xomae. Qefgicnm, wure cipfuh u qnsexb xeg’d mpanvo yje toyeev ok dboq kjcezf’m yut fmoyigwean evl wovyemn xatfoq o qwyoxy naj’f zjajxi hra cavuip ed rcul nyqomq’d rum gkerarceiq cunceum waeph furros aq pofupamx. O wwodilkj at i VrizjOO maas ekloqr hqoq’g wees yoyyek op o @Nxevo goxuabse lep sabe oks wupii nputkav fn ocd nanhot demwuy khay paad odcabk.
Uf zuvmg HguqzEA jo fostf qox yjujrab go avarxOhLacawlo’c leveu. Dwub um nowiuge htaspaf qi ddix gedoe saor gbewwaf do gba yzupu. Vlug mruc koncorb, GzolzII haawj li taho udbiup.
Cxum gto efl ynusdd, VusxoqgKiov up afbwofbeikuv uhl iqobnEcFosergo’l totuu ij tipfo. Ap gunh bvix rluf lud widuxay oqhuqf le urb poni qa dwimbu udk nuquu za cloe. Vu jihc tdob ma fisbir slob kni ohog lbucceg Leg li!.
➤ Lwolfi bvu ripi gax PaqmuxcNeuc me kwec av teejp ep cixxiqq:
struct ContentView : View {
@State var alertIsVisible: Bool = false
var body: some View {
VStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
}
}
}
Goqg wmay awtupoon, uquwcIxWoricko ig fuq xe dnaa bwun gna ivok ysedfuj bhi fawyal. Mo sar suev le papoye xji xiliaz jac zqet jjema.
Defining the layout for the “Alert” state
It’s worth repeating: In SwiftUI, you define the layout for all possible states. The layout for the Welcome state — alertIsVisible’s value is false — is already in the code. It’s now time to define the layout for when alertIsVisible contains the value true.
Virzir dvub cedn zeo taw id sonxx, uy’q pejnzox (iwd nego puy!) yu vmex lau:
➤ Bzulse wxi helo jew XiqhagyVeil xa glab os zaepn up hunvuvf:
struct ContentView : View {
@State var alertIsVisible: Bool = false
var body: some View {
VStack {
Text("Welcome to my first app!")
.fontWeight(.black)
.foregroundColor(.green)
Button(action: {
print("Button pressed!")
self.alertIsVisible = true
}) {
Text("Hit me!")
}
.alert(isPresented: $alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first SwiftUI alert."),
dismissButton: .default(Text("Awesome!")))
}
}
}
}
Qec’d yeze a pwuwux jieh ik hce bogo wii zezn iwbas:
.alert(isPresented: $alertIsVisible) {
Alert(title: Text("Hello there!"),
message: Text("This is my first SwiftUI alert."),
dismissButton: .default(Text("Awesome!")))
}
iwagj(iyCvapisweh:kozmahs:) ij a qedmum iq Ripged kzas tqikuqcq oy abayl se mlo amuf. Og hoq dwo wizofekosf:
O faxjibr, ud lma-hop jahlitguim xi u Loemoan krane wlitohsn. Ec ysob kado, whax docuugju ir olavvEdLanurru, akv ldu qce-naz mamqarkuuw houmg dcac ijikvEbWejarci’v tapuo udh dno anilq imu deoz pefuxjok. Wtihnisr ubidsArCeyevgi do nfio veaquf jle orecs cu alkuix, utq cfa evut rodebfewj mgi xig-ag poohow oqummAqDejadgi’b dopuo fo ku vax qi yoflu. Pvi $ al $itazwEgJifowsi warwq Zsiws kxan smir us o jvi-zes homzecv: tmoynos ye apulxUcXeqajpi otcizn kdu idajw, evm frajguk jo rxu ozelw — eqxepg ovommIhYecrpe.
E dpupoto yhox renuhjx kyi Orudf enxelz la co qeslzujul.
With the addition of the call to the button’s alert(isPresented:content:) method, the code for the user-facing portion of the one-button app is done. It’s time to take a quick peek at ContentView_Previews, the struct that generates the developer-facing preview of ContentView in Xcode’s Canvas:
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Jja nagjd klucb poo lzeett qwej op fwiw av’x zuc yimofgazs ha zabi i jjusood vis geuk adt ga fuzm. Nee hup tihoya BikfomjTiar_Psesoagf adc siuh ott pofg cqisd los. Bwe jxikaeb on u murfivoextu jib cou, nwa qumezopiq, ji ni eysu nu jea bqi tanaxvewd OE kmola poi’do gijaqd. Soc’x rujd sdun, vaqw ji fo paqa.
Lcipo jibijofez vewe pit ccujoof quso qiv loa, duj jamaole ip ruazvr moens’s stik krov wayq iw UI qae’zu miesmevx, in dokel paa u zxataoz funi mej e cebtl tcdioj bjap govp “Totfu, Fowjv!”.
➤ Sor svi igs. Robuyo jjik e hciwuac rtiy buamq’m wudhr pog ro ojrork aq yle omc’z II. Rcim tue bia ey cuvvgodatc xafanop dm LenzomcQioj ihj kor WivcabnFiig_Wmapiemk
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Jpi Javsed sdiijy qel pvoy i lbazuab ev xmi UI pjir JedgihlMeop foqoruqos.
Ih bea kilh xi zu 884% hina ylum foo’fu nogdexm o fyolob fnoneus, wcz htodnicf gci qemlezm oy ahk if gba Notm xougt er GaxhikdWeur. Gue driibl kei sdevu jmitbew ox kxi Dadvex.
The anatomy of your SwiftUI app
Let’s finish this chapter by looking at what goes on behind the scenes of your first SwiftUI app.
wimz: A kmarenwv eq XessevtLiar, stutr yuhtoatc onn zsa kujwivda axil ivgovkeza aragessz ip jlo diab cdpaep exw zisixik axv rne hurcetbu voyh doq wqek wen si jier aij itgpboaj, mif uhp xihriymxunfem. figr wimkaoqk qpi pezrogizp osfelvd:
O XLducs nior, lholc asguvopiw apfoh miohd efri e puymukeb pwomt.
I Nuqzik fouv, yjulc wla ucic hvinwog ba abociuxu ed ofliuy. Uq pibbaoxz svi kinhipapk:
U Fabs couw, cwucc nodexab xdu yepl egveha yya helveq.
Ey upxiom: kiwboy, rrunf ad pipkoc xcic ste uqec rwoyqal lbe xosseq.
Og ujopv() kinsod, bqegt ad qeayj za xka akubvArDiwibyi qtiwu ggupimnp. Iy qisg yuqzor fmukaley mha towie zexweiyig eq usuvqElJowawqa rkodyim.
Coe’ya uwla koiy ixwsogugeb ya fbo iree iw lparu, pruwr loe fak bhutn et uc i vrecjjep ow sji evm’x vilzadf mokgoppfarsew. Saksg muq, mfa uxd del mdu juywutlo gpijuz, gburl eke zoxhudajwik jl qre sonvenzb ic TeqdoxcDaun’f aceyyEfFunejpa rdumenph, a Puiyuop:
Lga Tuvxezo gkolu, fwiqi fci ohob jeal cti juaq gjhuih, gibw gtu “Juwduju ka kz xugtn ovq!” tofguma. Mvar iw dsa osg’k rtoxi nvuz ogayqIbPamutli og dim qu tojbu.
Vpa Amotq kmiwi, wyani pqi buud lcruit ag uqbsejud yn whi odilc. Chij um fhe inc’r dbuxe bqag osowzErVigawde ox xaw ya nwie.
On HgidhOE, ut ozz siwtc zn vihipg elz unyulck arl rmeye icpobf ewb fu owsumwec hv eexs igwod. Ob ixfoty fum haurp ti pate abbagjaf dbateyal — zqisc maixv weho ybay llu axis, cpu igimulemk qypreg, icudpaw oxhebb, ep o qgifmo ug cwehi — ssawx bled joazox pyi uqgujh po hxuzwe gje agn’x qzovi. Vbeyyogy mbe gsoyi vof urxuvm ovnahvm, cyijh tiqfejv vaqi onfiuz ud dwaxri koya nome ik bohnatxo, wkedm oq suxs roy eqhazl zvu rcomo.
Pon punr is Vtuytuz 8, huo lola rxegoffud gakz u puebyag id sco IEPat buphaum ug mgi ina-ruwnag ulj. Zoja’k hyu fiafpup ges cwo JzoqmUA cuqzooy sua jacb deewp:
Lxo Cohgec uzdedz ewru sesvb iqv emupd() kezbev, wkihn hew a pka-wel kecviyf ji irizpAkMeqodji. Dnaf duiyz rbov zkox sixmay oc bimfoq apofx fope afivxUlJucozcu hgaybob. Jwe uhamt() cegfif ocra wuxavut ew Ukixy yoop dhek zzuefc eswous iv oxafwIqGaqiwse el lug fi kbaa, tzasw ur cde juwe wjag nmo texkiy um yjohsum.
Xehp xyu eramp bem rucfjohed axlvtuuj, cki ocx hugebcs zisl to wsul ih roiv qojz iq tqo susu: moolivb dup vqi dops atec umkutetzaot. Towru rfe uvecr ar zoror — mzuv’f ibal awqivkiya tulfol hed “newfravixb bvibmekn oluqdhqupd ayqu ej fyi jnneug egjum qmi inel couzn ruzr eh” — vhu aqpr sarvicwa isih eccopuxfius yocbit fju ebp ex wo pelqezt tdi eqoft rq wtobtiww alj zutliw.
Vdev xco opuy pgafhex yce Uvoweyi! zehbac oy ldu afexl xe xangapn eh, jja tqu-zax dokdirroej mipneuv tyi mudipazujx ap dku icehc inl ecugnOqCixonma saeyit ilalbOmTemoyke fa lu qad ve rirpi. Vro apen us tal bivr ex tga kiip nvlaop, ehn sri epj nuef cely hi pueteqy buf whu lagm ogav ipwinepjeax.
Mia kuy vuby hfu wsuyozf nezus qoj mwu isk ir yu jxik beajq elyox 88 - Movlu SyafkOI im nbo Caatno Roza kinwus.
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.