SwiftUI Data Flow
SwiftUI Data Flow
Manage state with @State and @Binding, and share data using ObservableObject, @StateObject, and @EnvironmentObject.
@State and @Binding
Use @State for local view state and @Binding to expose it to child views.
Syntax:
@State private var name = ""struct Child { @Binding var name: String }- pass with
Child(name: $name)
Example
import SwiftUI
struct Child: View {
@Binding var text: String
var body: some View {
TextField("Enter", text: $text)
.textFieldStyle(.roundedBorder)
}
}
struct Parent: View {
@State private var text = "Hello"
var body: some View {
VStack {
Text(text)
Child(text: $text)
}
.padding()
}
}
import SwiftUI
struct ContentView: View {
var body: some View { Parent() }
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView() }
}
}
This example shows a parent exposing local state to a child with @Binding so edits update the parent's value.
ObservableObject and StateObject
Share data across views with ObservableObject.
Own it with @StateObject or consume with @ObservedObject.
Syntax:
class VM: ObservableObject { @Published var count = 0 }@StateObject private var vm = VM()@ObservedObject var vm: VM
Example
import SwiftUI
class CounterModel: ObservableObject {
@Published var count = 0
func increment() { count += 1 }
}
struct ChildView: View {
@ObservedObject var model: CounterModel
var body: some View {
HStack {
Text("Count: \(model.count)")
Button("Inc") { model.increment() }
}
}
}
struct ParentView: View {
@StateObject private var model = CounterModel()
var body: some View {
VStack(spacing: 12) {
ChildView(model: model)
}
.padding()
}
}
import SwiftUI
struct ContentView: View {
var body: some View { ParentView() }
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView() }
}
}
The parent owns the model with @StateObject, while the child observes it with @ObservedObject to reflect changes.
@EnvironmentObject
Provide shared app state from a root view using .environmentObject(), then consume it in descendants with @EnvironmentObject.
Syntax:
Root().environmentObject(model)@EnvironmentObject var model: Model
Example
import SwiftUI
final class AppSettings: ObservableObject {
@Published var theme = "Light"
}
struct Root: View {
@StateObject private var settings = AppSettings()
var body: some View {
VStack(spacing: 8) {
Button("Toggle Theme") { settings.theme = (settings.theme == "Light") ? "Dark" : "Light" }
Child()
}
.environmentObject(settings)
.padding()
}
}
struct Child: View {
@EnvironmentObject var settings: AppSettings
var body: some View { Text("Theme: \(settings.theme)") }
}
import SwiftUI
struct ContentView: View {
var body: some View { Root() }
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup { ContentView() }
}
}
The root injects a shared AppSettings; any descendant can read updates via @EnvironmentObject.
Tip: Use @EnvironmentObject for global app state like settings or session.