In this demo, you’ll enhance a budget-tracking app by making it interactive. You’ll learn how to use the @State
property wrapper to manage local state and update the UI dynamically. Time to dive in!
First, open the starter MyBudget Xcode project located in the 03-Understanding-@State-Demo/Starter directory. Navigate to the BudgetTrackerApp.swift
file. This file contains all the code for the budget-tracking app. You’ve already seen how data flows through the app’s view hierarchy to display a list of financial entries. Now, it’s time to make this list dynamic by allowing users to add new entries.
Start by looking at the ContentView
struct. Currently, it receives an array of FinancialEntry
objects from the app’s entry point and displays them in a list. Change this so that ContentView
manages its own list of entries and can add new ones.
To do this, use the @State
property wrapper. @State
allows managing local, mutable state within views. When a @State
property changes, SwiftUI automatically updates the parts of the view that depend on that property.
Replace the let entries: [FinancialEntry]
line in ContentView
with the following:
@State var entries: [FinancialEntry] = []
By adding @State
and changing let
to var
, you’ve made entries
a mutable state property that ContentView
can modify. Also, initialize it with an empty array for now.
Now that entries
is local to ContentView
, go up to the WindowGroup
and stop passing the entries
array into ContentView
view since ContentView
has its own array now.
Also remove the array that’s being passed into the preview.
Next, update the SwiftUI preview. In the #Preview
section, remove the entries
parameter passed into the ContentView
initializer:
#Preview {
ContentView()
}
Now, add a way for users to contribute new entries to this list. Add a button to the navigation bar that, when tapped, appends a new entry to the entries
array.
Add the following .navigationBarItems
modifier to the NavigationView
in ContentView
under the navigationTitle
modifier:
.navigationBarItems(trailing: Button(action: {
let newEntry = FinancialEntry(id: UUID(), amount: 120, category: "Groceries", isExpense: true)
entries.append(newEntry)
}, label: {
Image(systemName: "plus")
}))
This code adds a button with a plus icon to the navigation bar. When the button is tapped, it creates a new FinancialEntry
and appends it to the entries
array. Because entries
is a @State
property, SwiftUI automatically updates the view to include the new entry in the list.
Now, run the app to see your changes in action. The navigation bar has a plus button — tap this button a few times, and you’ll see new entries appear in the list. This demonstrates how @State
enables dynamic updates to the UI based on user interaction.
In summary, you’ve seen how to use the @State
property wrapper to manage local state within a SwiftUI view. By making entries
a @State
property, ContentView
can update its list of entries dynamically. Changes to @State
properties trigger automatic updates to the UI.
In the next segment, you’ll dive further into how to initialize @State
properties.