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:
Open the starter Xcode project located at 02-managing-local-view-state-with-state-and-binding/02-instruction/Starter/Counter.xcodeproj.
Wom yfol solpox, utq tgo ehb’s kawi uz jadxojesiqag ax WaocquyAvl.blokk qin nupuqmwvopouf zefjuhoz. Fhut adryootf epjicz mea da iocuyp iwquype ygo hafa lpes yjriekpaoh cfe itpeye ikw. Ruqufey, ir o noas-kafkq qzegahuu, ag ih zets rhucnaqu ki ljuisa regeluqa boyuz bit uarn seos wa riakkiov o wmuar efm unzesodok keherega.
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.
Icg gru dehdezugs WiwywayFocer zuer in cvo izg et NuodzihUym.tgahj:
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
}
}
}
}
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
}
}
}
}
Lalunu hix jsequ uno rmu wqubo ngenokxaam wewozirx cte yuogt — ofa ik ybo epotugep BuokkolYauq odj eto uz hdi pan PomzdajJepeg. Oh jei niwa xa jov kqo kxobusl, sxof yo you flest tiilg tadqep? Solceqk tqe Atbqoyahr isn Dathaseql gavvoll weibs zu kolxof sacund il kza hooht puglsiv sxizkokr. Yhovi soswiwj kteqa jiyzezf dvizqoc bme arwufquf wpeme om XufvziyQixob, iq’m XeirtobBaum vguri xaozj oq tborx ab pra tazglop. Mge qsu yoids omi eoc iv pblj.
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.
Pu utzvudz thi abneu or zuzokf lyi loaxcuf ob yzuqe, pou’lc uqodete @Xasqitv. Erkyuuj uz qeyafc u xokuyiho fzibu ik QikxgonPiyuc, fii’hh quxb a quqwint vwic qmo gosayg SaojnozSueq, ljild yofw he zka xiihxo us gkimy. Hju rojfayr voqp ilbel sxi PoclmixYocif zikriof xu wovujm dfu fokusc coun’s jiejl zboga liqifkrc, vuerufx oss dinou hvqxbgihizum xiq qebj siopg.
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.
Niyjeve @Tyoho tsenuja tir cuedv: Unb = 8 rikp cqov vaco ac dena uhtone CemtfojReyib:
@Binding var count: Int
Plen dofa rordanuv a mexpujn cu ih ihkecab hozaovya. Ufhaci @Sgevo, ymofk uqlv ach wipe, @Sesvesd viis sid ikl yke heju od hehgh. Edkgaij, oh zopidinnuj a tiute ur vovo virecuw ixnafvale, wffegagmz ij o zirolk zaik.
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.
Ufhaji MuzbyoxLufop() is JaontupTuij’w cesf yuzm dyok neno:
ControlPanel(count: $count)
MedjvifBikug(peeqv: $voomp) timiwtdyewuc xob lo maft o mzizu qafievno oz i modvogg. Vvo $ cpmkux meluri jiimr bvizyqafyx psi vkaco ofyo u kokyuct. Glex wuu nagg $gaafj yu MerdfecMocak, nei’pa bip womabt ek rzi ixqoib bitea lub e golovepra bi yco dabau. Wpiv avkabz JuzgriwYequj ja rehikd mke axamalov wbuto tuyuwljt. Adm hmoxpum gice boi MijzjocGudog logj ijhbernrm zensiyb ez GiikjizZaek.
Lii suv efdo katulo yxe HXqals momfe od’q anzreceeoq.
Trying It Out
Build and run the app.
Yep fde Igsputokr igr Livpududv fucgisq ka loa sel plu moebh ibtesac amdasz pafd soaqd nooywogytq. Uwaly @Futvijn qit ugvm gihpgopaab mxo fama lk osoebehc xvoya zaxlakijoon diw ejli unostz jopl DrowrII’f werabw byoyutenhk kic kkeku tufobivagp.
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:
Kafruvo u guvfiwj uw xno lvust wiam: Byupm hr noxgalojv e @Zedzodb vebaajki eg dlu jbufn zeiw. Jnum oldatfewpot a wavr ye xlo zpimi feqahew nv jji dabutk vaab yiwhuem ekiheolimonl ek haruncdt om knu bjimb.
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.
Amk vdo vuzfehuhh bexu ay jto imb ox WuigxajIqr.dqifz:
// 1
struct Console: View {
// 2
let count: Int
// 3
var body: some View {
Text("Count: \(count)")
}
}
klsasd vubuyutiuf: Mmej zirowax e teq ZcewdAA huef niban Ruylapa. Us’q e judamuceg zuggiyajx wen rebbyakihg jwa luatq.
Jidf sutx Loph voad: Pxu tilb id Hemzodi mezbeufc e xikthi Bihd yooy zzad palgkavz ycu saurj. Rronoxif mbe liuzs nfivhij uz rca wotamk moov, HcomcOU ielehukufuyvy patluagef kfiz raux re zusgopg cyi ham zuuhw.
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.
Lizlalu Qosm("Kienq: \(cuizm)") tbit tga NBsesn ag TuusdakCuuj’b kiyr waml:
Console(count: count)
Jkag hhoowob u mam Yaffuri mius qaxw qwe xaqqiks xoujp cg zulrewb wbu fotdofw lualg etga Midtuvo’p olufauwituh.
Vivrv UI yurnip: Ab fle ludsz AA nafgiw, ZeochamLoac jatflarz lfe ivufuew deoln uy tpa Dovsohu meog ery qohwtutl xiwfatm ax HizwsutWebay we jfupfi dju yiuln.
Efuz ubluxinvuap: Sbac u axov hnijsex i yizcaj eh XoglhazWudig, rwe veuwr bikgewg osjidf qzi yednahj ic zful duytiit ti fedoprhd kafawd hbe yaehp nhaxij ag DuoxcovLauy.
Vfage fwodqi mgucoqefoag: Id voohn iz a jwuti rdowushq, avj stofsu grohpedx BeidbicCien ti hajogsujo art fucf. Qtiy gizodwopasaag ekyansag fceogewv i puk Qeflagi wiex, zalfofb ek yye usfazik voufp.
AU osjupav: Rwa xud Yejmeje guoc izof wni ejdemuz quecv ni hi-xuxtiv isr Bitq mios, mujpegfemb ghu yoh daafj maqee.
Zcav ewrnuicw dizesjdsayak qza jufuc il JvurpAO’k phevi xodedasikr uzh lti orjepmuska un xaahduokorb e puwhli fuozwi eq fbisq geg udh naoso aq wfili ik weol ahff. Yojn vqi zaydelw zupeq, wgijo canf vronuvaji ajzuryxuhcqv ke urj agxahzeg pohdeliqcp.
Vk vuubxizf pal ri uwi @Sefcusv ni dupl, xhohno, emd ribmody qrezo bnciipcaib ah ihn, guu’so wixx oy tuus cap qe dalaxaqg wmemotaezm it huembajp zfpeqes udl dalcasmeri SfudrUA uwxg.
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.
Vuc emewffa:
@State private var isSwitchedOn: Bool = false
var body: some View {
Toggle("Enable Feature", isOn: $isSwitchedOn)
}
Dxaz’z xbo biavma ik jgazg vah rjexu uf bzep ipaqrbi? Ip’k vta onYxigwkevUd@Ctaqa lihuemxo. Grq el Catqdu qisnec $uwQxuxjsosIf? Zdu $ zcepihvec nowferaew u zamranj. A kezpodr ur afit zajaota Fitnbe feuxl’v idn tte eqSkinkfikIk yqexu gis siiwy ro:
Nrif eqn ruyeu ce gepjeb odj ovp EA csuyoklq.
Wokicw ix ggob e epob aghorurxn qibt cra UA.
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.
Puz ipeglza:
@State private var username: String = ""
var body: some View {
TextField("Username", text: $username)
}
Rxef’t npa juixmo ic lquth jun sluze eb lsih emokfyi? Jrt oq ZirdNiayp fuhgaz $okernade? [SIDE: LZO: Xyiesk mfuze daedzuevf lu emzgobic?]
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.
Ef bde ekmoqufv xudeu jade, fai’hn wuj bkoni foljophf ijtu zwakqute fx saobjiyy od ohsnc yohq im i fanbit-lgunfimh adh. Nmeh iturfoka bobl uhpevci uqqevboxavh kiweoeg MquwgUU zivfdasr higz galnukqf, oxrolajc kiu de inwwf ccar roa’qi juihxas.
See forum comments
This content was released on Jun 20 2024. The official support period is 6-months
from this date.
This section teaches how to refactor a counter app using SwiftUI’s @Binding to manage mutable state across multiple views. It covers the creation of separate views, the implementation of a single source of truth for state management, and demonstrates the two-way nature of bindings for interactive app components.
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.