Managing Observable Objects With StateObject
                
                  Written by Team Kodeco
              
            
          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:
- You start by declaring a class TimerManagerwhich conforms to theObservableObjectprotocol.
- You then declare a property timerCountwhich is marked with@Published. This means any changes totimerCountwill cause the dependent views to be updated.
- There are two methods, start()andstop(), which control the timer’s function.start()creates a timer that increases thetimerCountevery second, whilestop()invalidates the timer.
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:
 
    
In this example:
- You create a StateObjectcalledtimerManagerwhich is an instance of theTimerManagerclass.
- The StateObjectwrapper tells SwiftUI to keep this object around for the lifetime of the view, even if the view is refreshed or recreated.
- In the body of the view, you have a Textview that displays the currenttimerCount, and two buttons that start and stop the timer respectively.
Try starting and stopping the timer yourself, and see the power of StateObject.
Note: The
StateObjectproperty 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.