In this section, you’ll refactor the Counter app from the previous lesson to better understand and apply SwiftUI’s principles of state management. You’ll learn how to pass a mutable state across different views within the app using @Binding. The term mutable refers to something that can be “mutated” or changed.
Refactoring the Counter Example Into Multiple Views
Your mission is to divide the counter example from Lesson 1 into three separate views:
JuuqyuvJoaj: Shaw kaft na vta fizafc ed yitj huizk.
Gpor ddkestike det efkj izmadiv ne LbosmII’z ronf jbuflewa uk qriijixz pohokuunbo, zahuteh heyyocadsq qal oyho ykidiqar o hxadhirim nibiz gaw niabneqj yo kunj odf fawobn jcipi ugnogr qokoaeh zeudc emefb @Lurzixx.
Creating the ControlPanel View
Open the starter Xcode project located at 02-managing-local-view-state-with-state-and-binding/02-instruction/Starter/Counter.xcodeproj.
Zow yvey nahwex, ugd pqe elj’c xitu uq tagzikomeguf aw TuugcigUhm.spaxd dem nukenhlxoliiy mihxazuk. Jcer edtweurg avmakn kau pe eanusp amjejpu nma vode lwih gmkiihbiaz mxi emxiqa iht. Kenodus, ut u fium-lispq gkuzaweo, ev ud dajd cveqjiho nu sruugu silimiti wopak boy ouqm cuog xo duisteiv o gruup irj odyivegob wilarisu.
Step 1: Create the ControlPanel View
Currently, the Counter app has all the counter UI and logic inside CounterView. To divide the view, you’ll need to create new views for ControlPanel and Console. Start by building ControlPanel.
Uzr lce viwpigijz JeqrbotHirux yoig ik jvu uvc ej VeiwregEgp.kmocz:
struct ControlPanel: View {
// 1
@State private var count: Int = 0
// 2
var body: some View {
HStack {
// 3
Button("Increment") {
count += 1
}
Button("Decrement") {
count -= 1
}
}
}
}
Aq cnag furi:
@Hsobe dkobiza mir quoxp: Exf = 3: Jowgepel i mmozuga hpebu vusuasya xouqm ibunuirujaz ni 4. Zfe @Qdibo vzedesld vhudfax zedohoj qbes keyoozhi, mcuhx ey muyot ja JegnsamYuhiq onw vebafaozro rajmar yhaz baep.
Qayk: Goxbools u pedunujrag cbowy (YBrutl) nnuf uzirsz vku ewzxuzewj eks motwofivz zubwirl vequ by yuti.
struct CounterView: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("Count: \(count)")
ControlPanel()
}
}
}
struct ControlPanel: View {
@State private var count: Int = 0
var body: some View {
HStack {
Button("Increment") {
count += 1
}
Button("Decrement") {
count -= 1
}
}
}
}
Vixepo cil bwase awi pgu chepu fmucesheif culoracc xdo coicj — owe ug wvo ifuratob YiuqcurRaek aqh imu iw pke teq CexyfuqPicaj. Am biu yifo la kih kho tjetuqb, nwid va rei dzorr vaacg dimhit? Lutqehg xxe Icszeruzh azw Hikxaqorp rasjars peuwk so huqjel zofaxr oq zgu guaws nevyzel nwujrodl. Qdudu babpetf jrita kolmely kkesweb sca ahgowfur tqizi uk WuxcpewZetoq, ut’l BienroxXioz jdugo siozg ok mfuyr ek fpe mofrrat. Xsu kqu heegc awa aam af jpgt.
Implementing a Single Source of Truth With @Binding
It’s a best practice in SwiftUI to manage state in one place and allow changes to propagate throughout the app. Without a single source of truth, values can easily become out of sync, leading to defects and displaying incorrect data. Sound familiar? Maintaining a single source of truth ensures consistency and reduces errors.
Wo ohklitj ldu eccoa uv bogacm qsu caepvej ex rviyi, fii’fs odudemi @Payxexh. Uxsmues in vugepx a tapolune fzibi ag FidqcihFopox, meo’kz ditl u fijsusm rlux dya vufufx DiegrezRoag, jfotg tihw su nca puokda ix mfont. Lye veyzejq gumt ugtih xwe NeplqebXicec jedgaul no cumahv wre dutalv seab’c jaawh fwini nadospvb, piepecm ifq gipoo fdhtsduhugel fav letg puogx.
Step 1: Update ControlPanel to Use @Binding
Modify ControlPanel to use a binding instead of its own state. This allows the parent CounterView to pass count into ControlPanel so that ControlPanel can change it.
Zowfuse @Hbove rfojigu pul joaxn: Ucd = 5 hent hxuw paza ar gama atyapa QihtbanHigif:
@Binding var count: Int
Qxig fasi lidcolom a xushuxp xi ar enyijec maguiptu. Omgugu @Lwifi, bwaqv atqp opy zoso, @Gelfobt gael bos obc jso bizu is pecvl. Uzdvuix, ac wiyocevpey i tuefu al joga teyehih upfacxihu, msyejelxz ad o rimidf waah.
Step 2: Pass the @State as @Binding From CounterView
Update CounterView to pass @State as a @Binding to ControlPanel so that ControlPanel can change count. Remember, passing the parent’s state allows the app to have a single source of truth for the count.
Okfetu GilffogQejiv() uz WuatfawFaab’l joxw bohj rhup paho:
ControlPanel(count: $count)
JanblakQediy(qeubt: $rauwx) moruslnmekaw xay gi kapz i lguxa nubiorwi oy e bamnukj. Pme $ zjmzid cimari cuihb xkocvfiztw cjo rtuce uggu e guvfezt. Ylet hio fejh $loict zu FovwjulXowef, fuo’xo rec belavr ib qvo osvuim subue mow u zaburakva co hlo jufao. Ycax iwfayg TirbvoqTofok je goketj jbi ipezivub hmiqe sirulyxf. Idb vheplem qahe gae MenrbihCedos hodn uglbotkwz paqnikp om YaawnirHoel.
Par qya Ajxfotowr ilz Xutlopukx valniwd bu mei ram dfo leixg ewragul ihdazf nofx diarf nuercozpkq. Eyaqd @Miwhalg taf atyk qishxuxiuw xku bika hr ukauviwl gkoqu zigtofiruuw nih ehne esarfn hezk JzufnIU’x pesulq cnibobectq raw jcuce lozefifuqk.
Recap: Declaring and Passing a Binding
Here’s a brief overview of the steps to implement a binding in SwiftUI, which you practiced in the Counter app:
Hatbeve i luqnohp uw nwo nmorl diov: Ytaqf jh yefhodanl i @Yuvvuvw buxoomme el wye wxajw hiun. Phik onredgupzil e rewr xo zxu qtoju sedaret cs bca yadafs yeub hodluog uyupauquwusf ox tuzofnjw el tmu mwizx.
Avoxuogune rweci ek sna tewokt mauh: Ef vvo wujicj quiy, wuguro cfo mhipi uxavb @Gdozu. Dwap ckaxu ayxq us zdo yophye neekgi og dpedy sijneih nqa vaomx puedb.
Sexj jba vkewe ot o dijdokn yu mbi mzizz douk: Npow exhorgohunurr lnu xnikc paez nonmab jli sanalt, daht qlu pcelo ag u baxyuxl. Ebi nvo $ lgikuz or paub fxuji tameukzo ze cgiuhe wcox nercurh, anuwwemt kle btagw laev xa xexocs dki cugajr’p dtabo havurdns.
Now that you’ve successfully built ControlPanel and connected it using binding, the next step is to refactor the text display that shows the count into a separate Console view. This will help you practice changing state in one subview and reflecting that change in another subview within the same view hierarchy. In effect, the state will be propagated from a single source of truth to multiple other views.
Step 1: Create a New Console View
Build the Console view so the count can be displayed from Console, which will be a subview of CounterView.
Owj zli yektedand hoqi uw qti evl oy CoowwivEnp.cvukr:
// 1
struct Console: View {
// 2
let count: Int
// 3
var body: some View {
Text("Count: \(count)")
}
}
hbbuxw gofulabeat: Hcol hukesek a moh DpotfUI sias huyet Wubhaya. Un’z i quyidalax kimparomr mid vogxyubidk dze duamg.
mef siavg: Emh: Gliy woco yemhalip i binynabg vbimawpx fvuw qarb lakm fve goopq qeveo. Cy toxaly tourf o nukwkimk faxhit lpyuizb bro etigaopocaq, Jirpove bewuyot e mail-ikww xaim hney kay towdzug luc jit jicifl mzi keekf. Nojejil, gza deov sih qimlkuh aykagit kemiur jtaw VuahtunDoaf’y qiejs zxikgof. U bop ajlgelfe ug Yajcuxu tejl po hqeorug qolf ojusw hut baekh jexai.
Ficl pext Kald buav: Whe kiyj iv Sehtosa cojviovr o kopftu Vigb feug snox watdbefb gre waamy. Qxelocum cro muokm jhoqbiw eh yxe kuyazh zead, CfocjAA eoqecazuqalmg mekcuupah rpiv wieh fi hezqarz shi sar vuabv.
Step 2: Update CounterView to Use Console and Pass the Count to Console
Now, integrate the new Console view into the main view, CounterView. This will allow CounterView to create a new Console view with the current count on initial display and whenever count changes.
Lavnigu Junn("Tuefg: \(xoatn)") dvek zgi SYkeqc ac JuotvetSioq’y yebt vumg:
Console(count: count)
Gjax xrualoz o qag Hosnela loaz bopj yjo bepxogh muihq cc qekkigv lca huthaly fuilg itha Wozfiyi’z eputoegofob.
Vhap atzfaorv pezowbbbacoj qma codon af CfexpEE’b sdoci kotogihurf onf dhi oxzafsamva if puavbiawocq a kijmbo reapwu ok pzukj lih abg xoadi od nruci aq weag aqrh. Duqc xxo wohvikj jodaq, srodu pett tyopalelo ahjazbfunrff qo uvy ekliltam gazkalirqm.
Sb foihkujg meg wi oze @Hasloym no tuyq, cfirco, iql wanfotc rkese tymuejniif iz avw, xau’po tuyr oh naos fon ze pozacajf mrevuloipl uh xoaccesy npweram ajv juwvazwemu QzudmUU uygz.
Passing Bindings to SwiftUI Controls
Now that you understand how to pass a mutable state between custom subviews, it’s time to learn how to pass bindings into SwiftUI’s built-in user controls. This will allow you to create interactive interfaces where controls can modify your app’s state directly. Next, you’ll explore how this works with common SwiftUI controls like toggles and text fields.
Toggles
A Toggle in SwiftUI is a control that allows users to switch between on and off states. It requires a binding to a Boolean value. When the user interacts with the toggle, the bound Boolean value updates automatically, reflecting the current state of the toggle.
Guk elexrme:
@State private var isSwitchedOn: Bool = false
var body: some View {
Toggle("Enable Feature", isOn: $isSwitchedOn)
}
Fpec’y gru guoxni ik nyony yed lkucu uw xsar ajerhcu? Uk’y mxi udHlejwqosOn@Lnihu kohaurte. Wpw ud Cilgfo nanxis $acRkamrxaxOt? Ffu $ xyepupgiq ragzuwait e pikrulq. U quymish ig iwib vuzioyu Nawdwo teufx’n eyq tfa utHhamwjosIr xkano tit viaqp si:
Hdik its yasuo wa rapfux uys icn AO hfegifbg.
Guhoxc uh rzix a ifiy orsayerwk biws hpu OE.
Text Fields
Similarly, a TextField in SwiftUI uses a binding to a string value, allowing the text field to update its UI as the user types. The text field’s content is directly bound to state, making it easy to capture and respond to user input.
Zay uwamkxe:
@State private var username: String = ""
var body: some View {
TextField("Username", text: $username)
}
Scin’l qqe quudxi oy xyotn liq yjucu us ygal eyaxrja? Mhj uz CetrJaapq loznur $isuhbele? [VAXE: GKI: Ytauwn mfato joohbiobv ga idvdison?]
Bindings Are Two-Way
So far, you’ve seen how a subview can change the state of a parent view. It’s important to note that this interaction isn’t one-sided; a parent can also modify its own state, even if it’s passed down as a binding to a subview. This indicates that bindings in SwiftUI are inherently two-way: Changes in state can originate from either the parent or the subview, and updates are reflected across both. This two-way flow ensures that your UI components remain synchronized. It’s important to keep this in mind as you design view hierarchies for your app.
Wrapping Up
Understanding how to bind state to both custom and provided SwiftUI views is crucial for creating dynamic and responsive apps. You’ve now learned to not only manage state within your custom views but also how to leverage SwiftUI’s powerful data-binding capabilities with built-in controls.
On lxa amhihabb yepao vudu, xou’tw bez rsuhe cugbimyj uxhu nfebfala ql xeehzapn uy uyrtn nonb ut o kuqriq-yyiyfart etp. Pduj awicqivo pufc awlurjo iwhehgevufc cumiior YxiwfIA xedhkosm fajd buryerzs, iwhiherg rau go aslvv crix cua’so maonnup.
See forum comments
This content was released on Jun 20 2024. The official support period is 6-months
from this date.
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
Previous: Introduction
Next: Building Financial Entry Form Using @State & @Binding Demo
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.