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

Demo.swift

ContentView.swift

App.swift

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()
} }

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

Demo.swift

ContentView.swift

App.swift

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()
} }

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

Demo.swift

ContentView.swift

App.swift

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)") } }

The root injects a shared AppSettings; any descendant can read updates via @EnvironmentObject.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *