20 - Managing Observable Objects With StateObject

In SwiftUI, StateObject is a property wrapper that you can use to create and manage a reference to an instance of a class that conforms to the ObservableObject protocol. This is particularly useful when you want to create a source of truth in your views that also survives view updates and refreshes.

Here’s an example. Let’s create a TimerManager class that manages a timer:

class TimerManager: ObservableObject {
  @Published var timerCount = 0
  private var timer = Timer()

  func start() {
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
      self.timerCount += 1
    }
  }

  func stop() {
    timer.invalidate()
  }
}

Breaking this code down:

In your view, you create a StateObject to manage your timer:

struct ContentView: View {
  @StateObject private var timerManager = TimerManager()

  var body: some View {
    VStack {
      Text("Timer count: \(timerManager.timerCount)")
      Button(action: {
        timerManager.start()
      }) {
        Text("Start Timer")
      }
      Button(action: {
        timerManager.stop()
      }) {
        Text("Stop Timer")
      }
    }
  }
}

Your preview should look like this:

Using the StateObject property manager to manage a timer object.

In this example:

Try starting and stopping the timer yourself, and see the power of StateObject.

Note: The StateObject property wrapper should only be used for properties that are initialized within the view’s initializer and that represent a source of truth for your view. This ensures that the object is only created once and persists across view updates.