StateObject is not deinitialized when List(selection:) binding

Hello,

I have a simple example using StateObject and List. When I bind the List(selection:) to a property of the StateObject like this:

List(selection: $viewModel.selectedIndex) { ... }

I noticed that each time I push the view using a NavigationLink, a new instance of the StateObject is created. However, when I pop the view, the deinit of the StateObject is not called.

When is deinit actually expected to be called in this case?

Example code:

import SwiftUI

@main
struct NavigationViewDeinitSampleApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                ContentView()
            }
        }
    }
}

struct Item: Hashable {
    let text: String
}

@MainActor
fileprivate class ContentViewModel: ObservableObject {
    @Published var selectedIndex: Int? = nil
    init() {
        NSLog("ContentViewModel.init")
    }
    deinit {
        NSLog("ContentViewModel.deinit")
    }
}

struct ContentView: View {
    
    @StateObject private var model = ContentViewModel()
    let items: [Item] = {
        return (0...10).map { i in
            Item(text: "\(i)")
        }
    }()
    
    var body: some View {
        List(selection: $model.selectedIndex) {
            ForEach(items.indices, id: \.self) { idx in
                let item = items[idx]
                NavigationLink {
                    ContentView()
                } label: {
                    Text(item.text)
                }
            }
        }
    }
}

Interestingly, if I instead use a plain @State variable inside the View:

@State private var selectedIndex: Int?
...
List(selection: $selectedIndex) { ... }

Then the deinit of the StateObject does get called when the view is popped.

Because there's no sign of deinit being triggered in the first pattern, I’m starting to suspect this might be a SwiftUI bug. Has anyone seen this behavior or have more information about it?

Thanks in advance.

Environment:

  • Xcode: 16.4(16F6)
  • iOS Simulator: iPhone SE3 iOS16.4(20E247),iPhone SE3 iOS 18.4(22E238)

I've posted FB18710603

StateObject is not deinitialized when List(selection:) binding
 
 
Q