Property wrappers like @State and @Published help you keep track of data that can change. They automatically update your app's screen when the data changes.
Built-in property wrappers (@State, @Published) in Swift
import SwiftUI struct ContentView: View { @State private var count: Int = 0 var body: some View { Button("Tap count: \(count)") { count += 1 } } } class Model: ObservableObject { @Published var name: String = "" }
@State is used inside SwiftUI views to hold simple, local state.
@Published is used inside classes that conform to ObservableObject to notify views when data changes.
@State holding a number inside a view.struct CounterView: View { @State private var count: Int = 0 var body: some View { Text("Count is \(count)") } }
@Published inside a class to notify changes.class UserSettings: ObservableObject { @Published var username: String = "Guest" }
@State with a toggle switch to change a boolean value.struct EmptyStateView: View { @State private var isOn: Bool = false var body: some View { Toggle("Switch", isOn: $isOn) } }
@Published property in a model class.class SingleValueModel: ObservableObject { @Published var value: Int = 0 }
This program shows how @State keeps track of a local number inside the view, and @Published updates the user name in a shared data model. Pressing buttons changes the values and updates the screen automatically.
import SwiftUI class UserData: ObservableObject { @Published var name: String = "Alice" } struct ContentView: View { @State private var localCount: Int = 0 @ObservedObject var userData = UserData() var body: some View { VStack(spacing: 20) { Text("Local count: \(localCount)") Button("Increment Local Count") { localCount += 1 } Text("User name: \(userData.name)") Button("Change User Name") { userData.name = "Bob" } } .padding() } } @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } }
Time complexity: Reading and writing @State and @Published properties is very fast, constant time.
Space complexity: Minimal extra memory is used to store the wrapped values and observers.
Common mistake: Trying to use @State outside of a SwiftUI view or forgetting to mark a class as ObservableObject when using @Published.
Use @State for simple, local state inside views. Use @Published inside shared data models to notify multiple views.
@State keeps simple, local data inside a SwiftUI view and updates the UI when it changes.
@Published marks properties inside a class to notify views when data changes.
Both help your app stay in sync with data changes without extra code.
Practice
@State property wrapper in SwiftUI?Solution
Step 1: Understand what
@Statedoes@Stateis used to keep simple, local data inside a SwiftUI view.Step 2: Recognize its effect on UI
When the@Statedata changes, SwiftUI automatically updates the view to reflect the new data.Final Answer:
To store local, simple data inside a view and update the UI when it changes -> Option CQuick Check:
@Statemanages local view data = B [OK]
- Confusing @State with @Published
- Thinking @State is for class properties
- Assuming @State handles network or async tasks
@Published property inside a Swift class?Solution
Step 1: Identify where
@Publishedcan be used@Publishedis used inside classes that conform toObservableObject, not structs.Step 2: Check syntax correctness
class MyClass { @Published var count: Int = 0 } correctly declares a class with a@Publishedproperty and initializes it.Final Answer:
class MyClass { @Published var count: Int = 0 } -> Option DQuick Check:
@Publishedused in classes = A [OK]
- Using @Published in structs
- Confusing @State with @Published
- Missing var keyword or initialization
class Counter: ObservableObject {
@Published var value = 0
}
struct ContentView: View {
@StateObject var counter = Counter()
var body: some View {
VStack {
Text("Count: \(counter.value)")
Button("Increment") {
counter.value += 1
}
}
}
}
What will be displayed after tapping the "Increment" button twice?Solution
Step 1: Understand the initial state
TheCounterclass starts withvalue = 0. The view shows "Count: 0" initially.Step 2: Analyze button action and updates
Each tap on "Increment" increasescounter.valueby 1. After two taps, value becomes 2, and the UI updates automatically.Final Answer:
Count: 2 -> Option BQuick Check:
2 increments update value to 2 [OK]
- Forgetting @Published triggers UI update
- Assuming @StateObject resets value
- Counting taps incorrectly
class Model: ObservableObject {
@Published var text: String
init() {}
}
struct ViewContent: View {
@StateObject var model = Model()
var body: some View {
Text(model.text)
}
}Solution
Step 1: Check property initialization
The@Publishedpropertytextis declared but not initialized, and the init() is empty.Step 2: Understand Swift requirement for properties
All non-optional properties must have an initial value or be initialized in the constructor. Here,textlacks both.Final Answer:
Missing initial value for @Published property 'text' in Model -> Option AQuick Check:
Uninitialized property causes error = A [OK]
- Assuming @StateObject can't be used with ObservableObject
- Thinking Text can't display String
- Believing Model must be a struct
Solution
Step 1: Understand data sharing between views
When multiple views need to share and update data, use an ObservableObject class with@Publishedproperties.Step 2: Use
The main view can use@Statefor local view data and@Publishedfor shared data@Statefor local state, but the shared user name should be in a class marked with@Publishedto notify changes.Final Answer:
Use@Statein the main view and@Publishedin a shared ObservableObject class -> Option AQuick Check:
Shared data uses @Published; local uses @State [OK]
- Using @State only for shared data
- Using @Published in structs or views directly
- Not using ObservableObject for shared data
Ready to prove it?
Pass the test and this pattern moves unknown
