@Observable/@State memory leak

Not sure if this code is supposed to leak memory or am I missing something?

import SwiftUI
import Observation

@Observable class SheetViewModel {
  let color: Color = Color.red

  init() { print("init") }
  deinit { print("deinit") }
}

struct SheetView: View {
  @State var viewModel = SheetViewModel()

  var body: some View {
    Color(viewModel.color)
  }
}

@main
struct ObservableMemoryLeakApp: App {
  @State var presented: Bool = false

  var body: some Scene {
    WindowGroup {
      Button("Show") {
        presented = true
      }
      .sheet(isPresented: $presented) {
        SheetView()
      }
    }
  }
}

Every time the sheet is presented/dismissed, a new SheetViewModel is created (init is printed) but it never released (deinit not printed). Also, all previously created SheetViewModel instances are visible in Memory Graph and have "Leaked allocation" badge.

Reverting to ObservableObject/@StateObject fixes the issue, deinit is called every time the sheet is dismissed:

-import Observation

-@Observable class SheetViewModel {
+class SheetViewModel: ObservableObject {

- @State var viewModel = SheetViewModel()
+ @StateObject var viewModel = SheetViewModel()

Does this mean there's a bug in Observation framework?

Reported as FB13015569.

@okla I have exactly the same problem and wrote about it here: https://developer.apple.com/forums/thread/736239

Can someone from Apple engineers help with this and confirm that it is a bug that will be fixed?

We are also having this problem. Can someone from Apple engineering conform if this will be fixed?

Any news?

This issue sadly generally affects instances of reference types stored as @State, even without using the new Observation API. It can therefore be considered an iOS 17 regression since storing simple reference types as @State without @ObservableObject was possible without leaks on iOS 16 (I can also confirm that the issue does not arise with @ObservableObject conformance).

Though in general you likely want automatic observation, sometimes being able to store an instance of a non-observable reference type for the lifetime of a SwiftUI view is still useful and legitimate. This is for example how you might store an AVPlayer displaying its content in a VideoPlayer view, as show in this official code sample.

I also reported this issue as FB13126425. Sample code is available here.

The issue has not been fixed in the iOS 17 RC published today. I guess there might be troubles ahead for early adopters of the new Observation API (but not only, see my previous comment) when the owning view is presented in a modal.

Seeing the same issue

Excellent news, the issue has been addressed in the iOS 17 beta 1 released yesterday. Thanks to everyone who made this important fix possible.

@Observable/@State memory leak
 
 
Q