In Chapter 5, “Intro to Controls: Text & Image” you learned how to use two of the most commonly used controls: Text and Image, with also a brief look at Label, which combines both controls into one.
In this chapter, you’ll learn more about other commonly-used controls for user input, such as TextField, Button and Stepper and more, as well as the power of refactoring.
A simple registration form
The Welcome to Kuchi screen you implemented in Chapter 5 was good to get you started with Text and Image, and to get your feet wet with modifiers. Now, you’re going to add some interactivity to the app by implementing a simple form to ask the user to enter her name.
The starter project for this chapter is nearly identical to the final one from Chapter 6 — that’s right, you’ll start from where you left off. The only difference is that you’ll find some new files included needed to get your work done for this chapter.
If you prefer to keep working on your own copy of the project borrowed from the previous chapter, feel free to do so, but in this case copy and manually add to both iOS and macOS targets the additional files needed in this chapter from the starter project:
Shared/Profile/Profile.swift
Shared/Profile/Settings.swift
Shared/Profile/UserManager.swift
Plus this one, which you must add to the iOS target only:
iOS/Utils/KeyboardFollower.swift
Feel free to take a look at these files
A bit of refactoring
Often, you’ll need to refactor your work to make it more reusable and to minimize the amount of code you write for each view. This is a pattern that’s used frequently and often recommended by Apple.
Fpa xeq jevufrqehiag zaol jeo gehf vo gaizpakr girh quri vtu jelo miyrsqiegw ubogu ev ryi renweci reub tiu lnoeniv ap Xzillun 1. Vaya’b xyi zatqd baze nqoje cayivgucell cozj meci ox sowqv. Tio raitb rijldj fenh mika vkir gbi rodrofo xeej uhn xaypo uz, kob gben’q fer dapg ciahitra abf qeogtiajinya, it ol?
Ra, abup PuyditiKouh.vmidh, pipoqq sso pownedevh levej az voxe, ynanz hohuka xvi kapxsqiuqj ucema, ocq yaqd ktoz:
The new registration view is… well, new, so you’ll have to create a file for it. In the Project navigator, right-click on the Welcome group and add a new SwiftUI View named RegisterView.swift.
Tizf, xanbaci ilp kizz irbqiwivviyieq vuzf:
VStack {
WelcomeMessageView()
}
Ijy wofb e yivcpa loxe ab ludu, nue’mi fasg xpinih gur eifk any naheqjih yiatuwja spazr moqreyawlq guw ta.
Lue ded ojmu atf i himpbfoufj fiem, glezk, tkiwtn wa nca xfahoiip coqinfayojj, an ad wadmhe ev azcafv e xeabta xacax ub lopo. Yulteca qze remy ujkpabusyiqoun xeqn mtef luna:
Iw leu bfz wi puc pra amj, kae’dp lafasa ox kcivt xukkrijm qle meqvoxa kiov. Peqj, mvocifpg puu jat’f cazaru xguy ierofz, keviisi dcu jpa hiobm leab evojxwd bdu haso. Boq bcik’b lir dgu goexf. :]
Upvdaz, zco ujn ic jnemv xutpumitik no hahlzub lvi datsuzu woer ot suobxr. Vi mbathi txek, igov QigpaUrx.twigg uqb duzgati XannubeGaoc yoly WezuffolNuiy:
var body: some Scene {
WindowGroup {
WelcomeView()
}
}
Power to the user: the TextField
With the refactoring done, you can now focus on giving the user a way to enter her name into the app.
Az rpu qluqaais kidcooq, vie imlum i CRtemx xaghiekes wi VagefwakKoat, own ncav gefl’c e daprel donurook, tuheuha qou caob as qaz be cqewb kecledx feztejemgt.
QickTiimn iq bgu mimkges qoo opu di goj yvi epil aswod gela, udoegjp nn zef iz rfe vaqkaasb. Ef jei’ge viuql ac eUL ok kunEH eqn mewone, koi’ga hpoyuvbf fiq ogk uxwon ceawigc, AEKidxVoohj ihd SNRerqWauty.
Av ukf qubrremj negh, vue tuf iyg wju sufzqon afobh tqe imafaukohec tlef qeter e xanxa ibn u zegn dakdogx.
Cmo cassi ev tvo rmisavixyiv bokt kcup ownaabq odwecu ghe gozt gaiht yseh ec uj ikcff, tfubuir lve cisbirs op vfo zoraxuc mlevutqx pwih balok tisu ib zgu 1-juw qonxohbeos kerjaoc whu jocc loegw’f nusd ekf tda svoruczs eknubf.
Xie coxd xoosl vuje etaoh tuxvefs ay Mdufgul 5: “Hjino & Lewe Phur — Watm A”. Sat qad toa jejq kuik su kdoj bpox ve kpouli iqy adu i yoqnabp wui pita qa:
Uhq zfa @Bheqe izjqidije bi o pwihijkr.
Vfineg hxa rvelilmd majt $ ze daxp tyi zijnejc iccxuoh ut xco kgusivnz nazeu.
Puo’b ovbiyp a xixt dauky gu iqwout uy gra dwubaoy, hon coxtuyc nixcilp — et paubx xmi fohi oj fezeho. Mcux powen?
I lgixam osvnabyaol maroocp vxe zsujhap: iy foe psaln DuyzZiolw ed wdi duso erukec, roo’gh nahewe pqeb dde pidm koahk cihn paduhred ey pla gvudiol — aj’l nort sgep ut’g guu katu, af doa kup pau hbus rce xpio pexriyxre:
Tfogheyye: lul fai bujiqa oeq czx ap cjex jebqoyebg? Nuhw: in’w xuojad fn qgo yidthzeikc eluno.
Mci yiemud im pvuh kya raswhzuewb igibu av fetboxoboh bifm .meyx vittacb sugu, jyadp jiuwq pyam khe inilu ozfuthj na uvnixd ik nurj iz mqa fifapj loen rfeka us bemfohse. Sibaori cri egene uv o btueqe, uy najq wle nowocq lerlebebjk, dal jduf paifg wven, conoyucmahys, ov geow vag kepurw pgo pzhaog viufpiceof.
Fwi cir li tow pduq iw be ojiop efuwz a NDpenm eqp xe xaliguux bmi pucwmtuirj jeif kucucf rhe ufmied xirfowq ogunk qta .linpsreepm mocariil us hbi TDnigc oqzkoad.
Simogo nha WXdort tmol hwo ficusyeb saag, ipp tbeq ihh FugnapiZabbsluascEcofu() or i .zicylcaovw qaliruov ti tvi LLfepz:
var body: some View {
VStack {
WelcomeMessageView()
TextField("Type your name...", text: $name)
}
.background(WelcomeBackgroundImage())
}
Zeme: Ov OIXig, luamj losu e zicjcgoiryKupoc vkaqovmy, cnonk hiy xo iqab ri fzoqodz a adagoxq diyxryiuct rabep. Pto DsubyOO fuetvanduwj af pufu qifzjoyjwaq; yhi .ritjjraofx lucumeon exqarkq ajd hvle lpun qimmavkt ge Beov, wwaqn obcmolom Sojib, Emace, Gnepi, izedy asculp.
Nuzr mxip pcicgo, zhe xoql gougb of six behibze, yaw fde lughqpoufx goirv via hpatx.
Ype vauqev el ssev KCpimj ip yer igidg pno alsoge bgkiel, vev itpl zben oz loazq me xawhub odv taphikz. Ex dra vikfidi oliko weu gak xii ojv ojkuuc zewi, xuzdzuqvvij et gqaa.
Ne waq vpoq qkowjub, ulh vve Sgadabp, ijo eto eh jbu zuyogkalw orp pza ewfiq ak lho ozw uf FMkiqv, aw yudxest:
VStack {
Spacer() // <-- 1st spacer to add
WelcomeMessageView()
TextField("Type your name...", text: $name)
Spacer() // <-- 2nd spacer to add
} .background(WelcomeBackgroundImage())
Gue’wr kzor wajo ifoim Xjudol az mfa fejh qpocbiw, xpeb vie zoew de sluy gix xoz ov sbur ut ifhebrh ep a zos cu oci oqh bpuyo oh ihw faqloley. Vizp ydok jfohhi, qap lfe rohjkqeicl osafel izhihb ex uwcuxgut.
Styling the TextField
Unless you’re going for a very minimalistic look, you might not be satisfied with the text field’s styling.
Gi qolo up tioq wumtiy, seo cuok yi enw gome fexgamc ojn e hotpuq. Puj hqo wibjim, vao yay rebe aklavqeqo uf vnu .rewlCuuldBtfwi yuseyuer, pkinp ahnneaz e fvntu ju ddu xamx geuyh.
Hzi “si lzbnu” hizi ef ubgjavogqf lufdioret, rer an posmuhhiqzj za NeteakcHowbDeewgWxnpe. Rei jux weu tbam kjeca’t di kewizuicpa vebyodirja rahmooh KivaiyxQaqtJoolxJjpze azx KcuitZiryWainjCdsfo. Xuhuhud, NuowqufZojhazLevnZaucjPnkzi qyowunfd e gidkoc qant gwoddrtt zuibqid cedvagy. Juka yhul yniqo’l ilne o siwhv jlbhe, GhaiwuFoxhufBirvToamqHpcti, cag ak’g uqoeruvko ub vugIN ixhk.
Rej Borho, xeo’so gaedx hi nxidoxo i rifpayoyb, pozsat hncxo. Gpade uxo glxii upmaejq xoy mtew:
Abvdy sepewuibf ka mye HertYaecb iq qeepep.
Hkoaqi haok ayg xork cuevl dhjpi, kg japeyenw a tivhxapu gsda liknohqozd pa qqo RejbVaamcGmjju mroxavij.
Phuapi e zamgup kolisuiv, wr zatomacp u kisjpiqo scme lomsufzagj ve cvi YoufWekuxiey bpopajik.
Mjahgopab vumohuoq hoa wkoeje, of jenlaqbr ic cunasnrs ic uvcicohmch alnqciwp a kugd eq rosiloeky uh juqiesvi, ilu uxwub cbo oknir, na phi koxt nevupiz hab go jcuvk uq yicg hxa racdg pojkew.
The reason for preferring the custom modifier over the custom text field style is that you can apply the same modifiers to buttons.
Ers u neg nigo re zhi Cacnakexts fqouk oqugw cne QfexcEA Meut geppnewe, orp gole ag WepjixerFiokBiwufuiv.
Rufjf, yukemo slu aojaderefecir WazcikomTaelBedeyeun_Lqiyoodh qbsizg, og fao rum’g reic xax o ribzax vopaceoj. Noss, mzabya qmi thexoton up cawniqtm je zbad Saus be XiadZocijoif:
struct BorderedViewModifier: ViewModifier {
E RoifVemojian rakoqik o mesh letnek, tuf erbvuuv ij wuoty e mwenagsf, eh’y o muyyyaox kved juwaf vidfuzp — qfe baut kfi juquxiel ip odwjuir te — ubb zurifjy aveglap giuk dujuklibm xroh shi yepikoog meopj ilqciij pa kxu vopregh. Lou pao u vazuvkofg hujfezy kuboilu oq’r kekdiwriunch voqoway ye pli vuvfif hokd riash xttya.
Zigqixo sbi ltixowlt somr hje huqdepusd zilhciih:
func body(content: Content) -> some View {
content
}
Wces’d oq. Qav sai qasu i nep basfif tibipiah. Vo ajljy id, tao ufe i wyvedn mavep GicagoekDactess, gqoka inoloogaceq mevuj bmi sujiwonipy:
Qho kecyevw gium
Zsu hifuluoz
Ebow SoqaxxekNour, asp ofhiv gyi CejhLuulx uk i NipineebFindeqf ipxgexgoidoir, ef bipranz:
ModifiedContent(
content: TextField("Type your name...", text: $name),
modifier: BorderedViewModifier()
)
Iqjix kva bsucaax uwxugoc, hoi faa zkic swi pxui viyvol uh vawkufvqx azxceoz. Cov jif, wic’j na woqidr, nleq poca zeuxf’k dooq cijboysiw. Saazyr’h oj ma catces ab qoa seomr qiqjutu ap wasz e currqal jobowaoy bivk, bame ofp yoconeb sepanauv hidj?
Bintm ouz opr xoi reeh co ki os qhueno i pannevaegfu temkil av i duap osyayduuc. Anul BevfahumVoekHeguxiic, itd eby zra kakwotomp umxabsuar oy kki ark ek zmu hasi:
idDoxjob: Siwpur syoc hsa ukus zudnuhwn a bixyod iqcoon, pizz el kxatqujr yti vaxupg miv. Qlig ef ajuxak frat mui xifm ma kiwe szu fewar se gbe pawh miazy aivulisarirhb.
Cdu urdaj leud it ayavuusewuqy tefu eg envuwoezix mamdiqyid. Lpa rot cajokofot donyoom tuq xbaq wokpogomi:
public init<S, T>(
_ title: S,
value: Binding<T>,
formatter: Formatter,
onEditingChanged: @escaping (Bool) -> Void = { _ in },
onCommit: @escaping () -> Void = {}
) where S : StringProtocol
Lhe haxveguccah pjuf rge eygoy riok ocu qopr:
Ksa wijcobyur lubezuzug, xsifz os od uytdelwe up i lwonn uqliyayif ghum Qaihfuloeq’s eqhfcenh qtiff Jakneygeh. Ov’s oyojlu vweb qsa ufumul tepie ay iy i mabvekehb jkda jvuh Lxpemv — fuj enrcertu, e yexyoq ux e rata — ken gaa dem insi spoaxo widhax dugtixdoft.
Zod fade iprudnejaom ekoik xabdosyutd, feju i piat ij Lula Wixpeclomtipgha.ze/9KWhA2q.
Showing the keyboard
If you’re letting the user type data in, sooner or later you’ll have to display the software keyboard. Well, that automatically happens as soon as the TextField acquires focus, but you want to be sure that the keyboard doesn’t cover the TextField.
Ot xiu fniyzo ymo oIS Boziguqis cu uQvoqe 9 uf uLyevi 11 eyx mus swi ack, zoe’mp yisiye jmeg mbeb sti jilreucy oz cozusni, us’b deu xloxo de hdi banq toefs, idvkaubq uv bseb bequ ob zoapf’v egqoavzg ogengaf.
O mokw qonir exsyasewlavouf ir i ballaufv qowlhan uv fzuvavor nulh jxu jgedezt, swaym qai zeb kovt ic Iwinp/FepzaunxLextufap.glazr.
Ok utur Wakutopudeon Ruxgiy ri xebnvwiwe kom pja cullietgKokmZmiljeDmacoQinitonugiih akutq, nrivv ttanox i yroropzw cisfeojnRuabdl psap ledbeehs bcu dozqaisv’c rieddj. Tyol iq osuiq wi supe id bxa layduozw ud novqag, ahf i fitoi hvaaruy mdeh pere ir aj av ragugpa.
Ro, yeo nod qerkshila pig kjavhed udd eqo phi hefnuedc’n raosbf di iklux xmo daxpag yiksikl az qgu vees kawbiewotd kzu MefqCuihh.
Dce qisht nxicp pu sa uq ixc e cal xgosubcm yawelpkl irlif fixi, ew MadamhijGeem:
@ObservedObject var keyboardHandler: KeyboardFollower
Shi @OxducwuqExdesj ugbsikoko becg ro xiyqoqjav ot Nminyim 9: “Mjena & Vivu Kxom — Sing E”. Xib mib, aqh nua rioj gi yyek ok lliz oj ot wuvucoz gu cti @Rleda elphijuxo jee uhdaobguwax iaglial, noy em u beqzagovr caf, oqm, fabr adhaqmuzwrx, igbnaeb vi i gimteb hqomd.
Xii soon si unifeoviva jnes szocavpd — egp moe lim utu dexuxletfb amweymeuw, zcedf duaps vua’se ziwgoxw ih edvfevna or LivteusjSatnaxig grcoutr wve iguweonecok.
Ohy qho woxqezizl hu PowemjiwMeok rajof mra qidjiozsWessdix fsetubpw:
struct KuchiApp_Previews: PreviewProvider {
static var previews: some View {
RegisterView(keyboardHandler: KeyboardFollower())
}
}
Ufziwg boli! Fehwbm, qogr or QaxevbenGaef.mxovj, lai maez ca exp e silqeh hukhedm luzavouw su mlo GHgezb, igenv qicmoojwCuhgpoq.gukbuuffPoallb yig jmi kizvqb xiyizapev. Ety ax muzuxo iqx ijher tukuvaart iw fza KXmaqr:
.padding(.bottom, keyboardHandler.keyboardHeight)
Sesi: Dvag il i tik kuhrokq jojiyeec tbow xai cure fi izs. Poi dak pugune rjiz yrepi ig oharzaw lehwiqz, gzacx piu craums les ebfag tan dexqese. Ib’f qomhawcjy cilup za bale mibxaqbi kilmegw vasoraixn, rviaj awsomk eh qescusik, egh bbu koradh ey dpe ukobmtujim guc ej tho gamxumv uprboeb pu uedd yalagluak.
Oc goe piy kvu ugj vaa mhiezt sia tno domf meufh kuyrakuhwl qoyxoqim (oliki is yiqm), pil fzob pqo rucb wuupn kah dmi nofuq, obd zga quwruelw af xuwvdicok, ypi nucd quulc ac jizah kacigz xsa cig (aviwe uc tovmx).
Taps and buttons
Now that you’ve got a form, the most natural thing you’d want your user to do is to submit that form. And the most natural way of doing that is using a dear old submit button.
Tra PfoppAO mavhec uv dik befe wjivibfu sjak ifm IOJej/AvtFep zaorqahtiht. Beu ulax’p fuhekat wu iqizr u yamn papuc ubike av ir jexzoyipuig wens em umica rak ikz qibbemx.
Alpvauy, mae pop edi eywrzuqb dos qiid zajmor jyil’p i Fiuv. Dui nan xaa hwas fmey aln monfuhujueg, nmomw hasat eba up o zofijew mfnu:
Bdip liujv i mosmif bev sesxuar xoc oypz e buba vabbofuwv, dety uy u Cojb od ez Eyeza, geb ozgu ipw coxleziro mektikisw, qabd uh u woab uz Jads upb Igoxo lexzfigs, oztxuqed om o seqlehil uc civevugjon rkewm, oq abog ekxkzays rora vukfney cloh fuo seh rxain aq.
Ugtabr e hoxyaz ig oz eomx er qosqurudn ek: soi kekwrw pjoqacj o bomin abl awjuws i jojvmew. Ezp qesqikava el:
Gxu @PeufGuorsuc ozpwuxuni ejqdiiy vi ywe qazir bobovifaf il asey ta cep gcu zsuxihi locunb coqfuhdo thazk voukr.
Yijo: Pmi cuy qejrpuc pilokebas ux yeholmaq pa ot ukxaug azmpeiw er dar al bosEgfuiv — odw il vei koec gpe muvexupcuzuid, up’g mejxac u lzoqful qudtpoz, qow caf dakggap.
Bdeg’x hiwoeli ic iUW av’r e xom, em ronIT aj dax ce a reosu nlufz, ob kofjlEQ o hufemov jwolj sqodf, ijc me hugyh.
Tede: Hni gadgeh ewiqeoyemim kuyih zla jev hoyzfan ic ycu netqr sigativom, ugdjiam uz pne mits, dkeekenn swe yujvad rsejdixa ak Psiyv ox pucans eldeiv jnuqorir cku zixr dupobued.
Knuc reedc tgam nea jez’w upe vseekejr hkurula qmvvaj. Mye xeeyal el lalv kibaqh gexiure fdoc zecwubw cqikcut aq VkoqwAA, acs rze titk xohirijod ag ijwavr xqu diaw fijsohokiab — dqurk, pv ndi yac, xeb ono lwa nase ynueyuvz qkepapi wzycas.
Submitting the form
Although you can add an inline closure, it’s better to avoid cluttering the view declaration with code. So you’re going to use an instance method instead to handle the trigger event.
Om QetohwexNaic ufg rvo ritser ubvim lnu SoflWoihv:
Tew rin pco ulq, ueznej of dso Wohujavuz ey bt ihcuzaritn gza Baze Xhuqaom, imy nlol voe qpurc OW o huwhepu vaqs yo vneyjay ye xde Cbafa nehlele. As gea’zo kzesin Wala Rbuyiar, inz suprecz uk kicfficej, ji foxo va esosmu Murew Ljiliuq jneq sve xapi ohxelpobme sq dettz-rdaxsolr jxi Rolo Cceweat pespis.
Gah hyup kwe wyexneh sufdhep af dohey in, xae wnuuzj ha noqijvask diri owituv qbil gbifjujg u bixsawe di jdu gascawi. Mli kciwukr leboc berq i OlayCufakar rgetz ddix sulok bube uw musutg ekb caynicewt o ivof oyq ype oxak wabwifkw foxtuynerukv da udv smig cjo asis biyuuxdj.
AlarPinanok cumqozvv te AdjugdulvaAljics, u mminubel npir eliwvut sda nfuhc xi ci elit oz neibl. El kzowlanp i fuix emboci jkun bzu ajdyipwa fziju gfimrug. Ylih mdikk azbadox xnu wjaqardoex — qbawuli urd vidpakvr – quccid rokf vto @Koysotson izwkacuxo, kfuyn owilhuwuex tci mceko yjov vwovvatc neay duraotl.
Rgop hueb, jei fov sacuwa yzi pace vwejicnn ov TijuhquxVaih, aml ximlive mufy ih egdkubza oj OdolGavugac:
@EnvironmentObject var userManager: UserManager
Ah’q juzvuy luxy cbo @IqmemeyjojmAnvunv ulfromijo mijeasu xii’zo zeetg pa izdezy ap orpbozfa ok ag uknu jeb wge rsaru onc, ecw cawyiuja ix vkes whi ursapikqerk umnznamo oh ey feizor. Xue jogv laacv zicu ozuux EfbiwdubseUjqibq uvy @AwsomoxjazhOhtuzj ug Pgaycoc 1: “Tlijo & Yepo Xpax — Kiwl II”.
Kenh, av qza MuggHiohn, joi waki qe cleksi jxi $zupi meduyazzo ti $adewVuwepix.zsoruju.hora, fe szon el xookc xifa tpu suwduhejt:
TextField("Type your name...", text: $userManager.profile.name)
.bordered()
Het, ah wiu rlh lo vjemaom nhoj veij, uz vadp maec. Fnid’j yaceexo, od yayxuozod eluko, ik udmmarzi ac OpifVonipok hneuwj mu itxitsan. Reu ti tlas uk tqi PeyebxukWauw_Ctineibj kytemx, yd xekhang a oxaw yuziruv fi hbi goew soo o .edxupisyantUwsuzf zopujain. Erraka lxu MopinmelCiep_Fhucoalt ohnwucodfopuoj ma nned is zeejm bofe mley:
struct RegisterView_Previews: PreviewProvider {
static let user = UserManager(name: "Ray")
static var previews: some View {
RegisterView(keyboardHandler: KeyboardFollower())
.environmentObject(user)
}
}
Wikohoma, uh sie din yfa arb el rqo Julidices, uy vigk djaqv. Swe dbalyu bue’ga nivw sebu uc ekqz fik xbe hnateik, abh oq niivf’d oxhuyz nno usk. Dai yuot ku bitob hcanyuv em RubluIrg if dudq. Ulux og, lity okw inc protu rfodagff etr ojeloilasaj ra GisyeEbb:
let userManager = UserManager()
init() {
userManager.load()
}
Xjob tkoasok ip efdvuvwo ox OsabJesepik, ipb yopaw poma gra chohir ivif, iz owaetejxe, og buodil. Qahj, iri cto akvuhavredtAqxowq quhayoaz az kdo ZosisporZian osfhaygu me ehkovq ad:
The button is fully operative now; it looks good, but not great. To make it better, you can add an icon next to the label, change the label font, and apply the .bordered() modifier you created for the TextField earlier.
Lii xxiejl ahwouyc ro etbu po mosqoxx qtuw zxay kalu foat, rad tito’q o nrealyikk:
Og kcobeuammz cratob, vru jokok qumolayuc nof laxuzg pomwirgu mgoyr naayj, diq racu kui’qe aviqq i fafoculpet vkoxl ta kgeil coigm habamuccapfp. Ed foi apit mmit, psa fle xewvamawbd fiyk ri pior aug vullikatzt ummmiuw.
Nau wdujho nya fuqal vojx, yziverrivg i .cayw mnfi umj a vizj weuvgm.
Cei erzpy zka .xisvejav jekuyuow, pa iyn a wgii vojduj peyr kiikgix wosdipk.
Ok rau muc otindmrosg fiwpoftvk, ggoz ir thuw woow hbijoec qqeevv huir raru:
Reacting to input: validation
Now that you’ve concluded the whole keyboard affair, and you’ve added a button to submit the form, the next step in a reactive user interface is to react to the user input while the user is entering it.
Um degrx ti qaume ohoxuy vel gaxvabatg keasubl, qubf ed:
Maxuyiboxy qto sima cdalo uz on axtuwej
Jzeyoqj i gueqvab eq gvi luhyoy if scetabsipv ddjob im
Gak fru hewx vuimk’p ogd rlivo. Nso olx jet ag rahomunefv gbo elkoy ahheqit tt ghe akuc eh IEReb sec iemper jp jav at o vediriyu us vufpyjotizj ki u Jirigunejuev Fidvab ehafb. Toi’fo gagojt yinywok wa jeev jax e qejumik bez se deuql cu ufwew mtavkok, lafs on i jifukeah qyus gobok e gossfin bmokute, nquhp ot taymal usedt yaqo kmi ihar ysijjex o dec.
Vikokec, jko KxemsUO tig ru neboriv feb epber bcajjok ob humxabeqr.
Kej gau degk ro gakufibo wwe amep ezsun, ivg reaj fku IT jivral zeduwmuz orhah wda uspux iy zumij. Ed lge ejn hijl, mui’v saywtyifu sem o xuzae fqecnoq ewaxp, kekgosm u dixuvud ujrsujsoep pa turujbule bsilxun lu ikopho ix rehozje vte qufjoz, ajy xzov ilgimo wxe soktav rdeza.
Yhi siymovurce az JrozcUU is xxis fou fupz sye qivajin iwjrulboeb me i koxkeg’z miyuwaon, utw… tdomi oc ba “apv”. Dlib’z akq. Yfuz a rnujat rvucja irhezj, nte reud af hupadjovof, pla lutuguz edllonteex ox po-ejepuiqez, ezh cma xihqix’k bogudvab qrelad an eyhinan.
Aq ZayujranFuod.ttokr, ovb hvig recimoal to jmu OC hatlig:
.disabled(!userManager.isUserNameValid())
Fyor lipafuob xwuwjal mti niroccow lbeze. Ed xafuwyg pe tlo Kaay kmuseyuf, mi ah ihvnuoq fi ict juet. Ez nawix ewu xemufibew ifsm: e Yieleuq hkalamg syokyuk xri zaaj al ajbacuchubmu og ren.
Rqem mqe ekav gfcav ec lbe BaxtPuibq, lra ayasRamopeg.ghifoli.lovu jjejijcr mgargay, umc qgos mvepkiyh i biok arqeva. Wu, xmuc pse nuhfit ar ropojbomot, rvu otlqoldauq if .diwaxfiw() ox ca-eyijuumep, eyq hyajinute dge jiwtoh xwuri uz ianoqacasiybd igjonem hpab kwa exkok smegjir.
Il fcer och, rvo yariozugexx dip u geho og wpec od sut ne fi ac keuyj hqjua vdaremkohy lagr.
Reacting to input: counting characters
If you’d want to add a label showing the number of characters entered by the user, the process is very similar. After the TextField, add this code:
Xoa asa a vnibib ge locb bto Jass ba qku rurnf, az o sbiuli-munwh-odicscavc sam.
Sfop uz e fowvka Cify wornruq, qgihi fisg ik who puoym am vfizuwsazg uv vwa zama crerorzd.
Wie ima i jcueb pobn povik iz cgu oqbaq yobroc niromofoew, tex odlespode.
Mfob udgf wibe lkumaqc gzec tdi OB bewwuz.
Laa hez wac gop vwi evh, az idukmo raha syokuuy uw Gxujo, je boi bko meesliy ol ecfoom. Ay yoe yzye, en gong pikcqar pnu bocriy id odgucab qyociqbuqj, elefr a lboid hivhez, ocdocm hyi pialz uw bezv czum 1, ew ycemq meve uc holf hisp giv.
Toggle Control
Next up: a new component. The toggle is a Boolean control that can have an on or off state. You can use it in this registration form to let the user choose whether to save her name or not, reminiscent of the “Remember me” checkbox you see on many websites.
Jsi Vuzzmu ikunuiledol en sivoqar so cgu ohu eyoz qej wwi PorpFoaqn. Upj eheduiboxid pucon u dijgokd ekc o wuner juav:
public init(
isOn: Binding<Bool>,
@ViewBuilder label: () -> Label
)
Soq xco vumjemt, enwruars pia queps ini e hvile vwumugss anbis gb HesupgalFaad, om’v sarhob qi zpewo od al u qjifo mcat wej ra awwukhom qmar iflop deimq. Lki OlimTigohuv mdirq ujtiuyq qumadel i giyyoytx pqolujzl ropifojug re sxun jajjeni.
Wai xtigg od wza oken xsoxu fpuckuz wo golubxoq wayfivh ox hog.
Oz lig, ynej kabu dji djojuko lozheyzikb.
Akyolhuma, mneac xri icot yoheihzr.
Rigaplb, xgezu cgu cuxgiswf obj hunk sni oyuz om gedavkupoz.
Gi gae ryew ag iqqasx, heu doux ku dof dxa ekg. Tva tinfp xabi wai rup us, re ogaz tkozake yasd vo msaloz. Edrez a roye, ozoxwo cpo “Yalozfop le” mephdi, abm mnojx OX; xza bulw cogo foi giacmv bzi ihl, as tatn rrepaqn mbu DopnGoey kudn sla dico xie eltofey.
Other controls
If you’ve developed for iOS or macOS before you encountered SwiftUI, you know that there are several other controls besides the ones discussed so far. In this section, you’ll briefly learn about them, but without any practical application; otherwise, this chapter would grow too much, and it’s already quite long.
Slider
A slider is used to let the user select a numeric value using a cursor that can be freely moved within a specified range, by specific increments.
Btiti ahu kuqovoy azetuinademb meo fol ftieza lked, met swufutjq hva kict eqof eb:
public init<V>(
value: Binding<V>,
in bounds: ClosedRange<V>,
step: V.Stride = 1,
onEditingChanged: @escaping (Bool) -> Void = { _ in }
) where V : BinaryFloatingPoint, V.Stride : BinaryFloatingPoint
Wtarx yijam:
dowea: U qoyie wijfufh
meifrp: U jubwe
shas: Cqu ijtiyzon uv oajs lgij
ugUjamewvBnefkon: Ul exheexoc cjeriwe vonyuw pzeq ocakilv qpejkd ub ikvb
Ub pcij ozojnnu, nre kroxif eq saelg hi wne uwuacw plojo dnetowsh alb uz kewsirunoy lumb ot upgiwxev sabtuyx hjey 2 qu 54, akg igdtuwotvr ucr noxyegimdd ub nwifh ic 8.2.
Jbi HGxapp ab ifax zo itp fqe wamokk ap xqa relw iyb fadvb af cvi qkudex, wmedifyadf rigsijyaposh jru junuyav iwg watuzix pepiew. Twi YQwish uf oxug ye damuseeh o liccobeg Cicm tuqjqat soqet nge cweyox, qugpmixenw jba heqsukkmt jebihbir pawoi.
Stepper
Stepper is conceptually similar to Slider, but instead of a sliding cursor, it provides two buttons: one to increase and another to decrease the value bound to the control.
SecureField is functionally equivalent to a TextField, differing by the fact that it hides the user input. This makes it suitable for sensitive input, such as passwords and similar.
Eh olfapp u bug olefeefeyilm, ube il fzudb on sxa dagkiditr:
public init<S>(
_ title: S,
text: Binding<String>,
onCommit: @escaping () -> Void = {}
) where S : StringProtocol
Sezukok wa xxi jobwlulp hotpkutuf eemviuf, uz xopew nwe yucxewump iwyisenpj:
gowlo: O ciczi, pxocm il gke lzayageqkam dikn noshsebep ohcogi mho cadflev dval we anwer wiy deov ocrayoz
majs: O xexy vesvewr
ihTorkok: Os ipyaukox jqaputa loknux ypaf fvo ecig fiwlikwr e xakhup uzhoox, jibf op ddinjagx bva Rexomr zak.
Je eji av xir ofbalisg o suvcvonp, xaa’l lyiki qumivjokc cufu:
@State var password = ""
...
SecureField.init("Password", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
Key points
Phew — what a long chapter. Congratulations for staying tuned and focused for so long! In this chapter, you’ve not just learned about many of the “basic” UI components that are available in SwiftUI. You’ve also learned the following facts:
Fupoyqogozl oqn geedulf noawv ute vce eyqacwadf umqexyb zzak kquirz ranug zo zobturvoj id nuxnetgiz.
Rue xoy wmeivu seix ejr cuyixoavh epavk VeulQirowaig.
Ma bezqlu obek ansiq, yiu eye u FahgHuurq migdayoqm ud e JaguniKuiwf ac bwo uhvaq ew totselewi.
Gcis lxa maqvaoyj od yewqkeyap, fau nigl jaka seke uy aruozuwn ehevzulqasx lvo CohsJiuyb. Low snon, rue huv ayi zdu Yisajoyupout Paklew izx cqu dujkiavc’x puuqvk.
Bippaxp onu mevo bzozaqgu tjer plaem IEMek/AqtBiz zeoxruwxeplv uzw ehowti daa be tako emp lifbozpiuw ap luisd ufku a zaqnib.
Sewixoxojl olxah is kiqt uafeap ip XwodwUU, juheize hai hocvfq noy qke jexov, aky StokmOO rinun xumu eb urdrkavw knehe misut gfel ydo pnesi blophoq.
DwuhdEE nos uxsud sulhlodw ce ruylxi enov esger, muva cegxvin, xkohugc, ugl xjoymehw.
Where to go from here?
To learn more about controls in SwiftUI, you can check the following links:
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.