StateObject isn't being deallocated whilst it's containing View has disappeared

Hi! Seems StateObject isn't being deallocated whilst it's containing View has disappeared successfully. Suppose overlay is the cause. StateObject hangs until next view body evaluation happens.

import SwiftUI

final class Copmanion: ObservableObject {
    deinit {
        print("☠️ Copmanion died")
    }
}

@MainActor
final class SessionManager: ObservableObject {
    @Published
    var isActive = false
}

struct CheckPasscodeView: View {
    @EnvironmentObject var session: SessionManager
    @StateObject var copmanion = Copmanion()

    var body: some View {
        VStack {
            Button("Login") {
                session.isActive = true
            }
        }
        .onAppear {
            print("CheckPasscodeView appear")
        }
        .onDisappear {
            print("CheckPasscodeView disappear")
        }
    }
}


struct ContentView: View {
    
    @StateObject var session = SessionManager()
    
    var body: some View {    
        Color.teal
            .overlay {
                if !session.isActive {
                    CheckPasscodeView()
                        .environmentObject(session)
                } else {
                    EmptyView()
                }
            }
    }
}

ZStack here is one of possible solutions as well as using Observation framework.

Conditions:

  • Xcode 16
  • Xcode 16.1 Beta 2
  • iphoneosSDK 18.1

Hi @badf00d , really interesting behaviour.

For completeness, I tried your example app on iOS and I confirmed that Copmanion state object is no deallocate since the next SwiftUI rendering (you could simply make a touch or click and see the deinit call) see log


CheckPasscodeView appear
CheckPasscodeView disappear
☠️ Copmanion died

This behaviour is equal on iPad 18.0 Simulator , but on Mac OS the behaviour seems as expected:

CheckPasscodeView appear
☠️ Copmanion died
CheckPasscodeView disappear

Note that at first touch object is deallocated even on iOS use case, then I'm not sure could be a issue.

Bye Rob

StateObject isn't being deallocated whilst it's containing View has disappeared
 
 
Q