Bindable is never deallocated

I've encountered a problem which I don't know if is related to swiftui, the observation framework, or both

If I run the following code I have two tabs, with the second tab that use a "lazy model" which is deallocated each time disappears (this is necessary for my use case)

If I switch to the second tab, all works right. If I return to the first tab, the onDisappear on the foo view should force the "Bar" variable to nil , because the FooView may be still allocated (it is a tab bar) but that resource should be released

If that bar variable is set to nil, the MyBar should be replaced by the ProgressView in the "background"

I expect regarding that the Bar that:

  • the instance is nil on Foo
  • no other view should be shown with that instance (MyBar is now disappeared)
  • Because no ref, the Bar observable object should be now deallocated

In reality the Bar object is still in my memory graph

Any suggestions? is it a bug?

@Observable
class Bar {
    var hello: String = ""
}

struct Foo: View {
    @State
    var bar: Bar?

    @ViewBuilder
    private var content: some View {
        if let bar {
            MyBar(bar: bar)
        } else {
            ProgressView()
        }
    }


    var body: some View {
        content
            .onAppear {
                bar = Bar()
            }
            .onDisappear {
                self.bar = nil
            }
    }
}

struct MyBar: View {
    @Bindable
    var bar: Bar

    var body: some View {
        Text("MyBar")
    }
}

struct ContentView: View {

    @State
    var tag: Int = 0

    var body: some View {
        TabView(selection: $tag) {
                Text("First")
                .tag(0)
                .tabItem {
                    Text("First")
                }

                Foo()
                .tag(1)
                .tabItem {
                    Text("Foo")
                }
      }
  }
}

Replies

When a view disappears in UIKIt or SwiftUI it is torn down by the view life cycle and is no longer active nor alive to respond to anything. To see the transition from MyBar to Progress the View will have to be active. Read up on the view lifecycle for UIKit as it is the under pinnings of SwiftUI. https://developer.apple.com/documentation/uikit/uiviewcontroller

  • I do not want to see the transition, I've a memory leak, Bar instance is never released

  • You will neveerr see it,

  • What you are looking for to happen is managed by the framework.