SwiftUI: onDisappear not called for ForEach child views

Viewed 31

In a MacOS app, I would like to know when a ForEach child view is no longer rendered. I tried onDisappear, but it does not get called. Is it intentional?

For the code below, after printing "Update", I expect to see (in any order):

Disappeared: 8
Disappeared: 4
Appeared: 16

But I only see:

Appeared: 16

The views themselves get rendered correctly.

Note: I can work around it by adding to the ForEach (or to the VStack) an onChange(of: nums) { ... } and filtering the items that are not in the array any more. But I still wonder why onDisappeared is not called.

Environment:
MacOS 12.5.1
Xcode 13.4.1
Deployment target 12.3

Thank you for any comments / answers!

import SwiftUI

@main
struct MacosPlaygroundApp: App {
    @State private var nums: [Int] = [2, 4, 8]
    @State private var timer: Timer? = nil

    var body: some Scene {
        WindowGroup("Playground") {
            VStack {
                ForEach(nums, id: \.self) { num in
                    ZStack(alignment: .center) {
                        Color.pink.contentShape(Rectangle())
                        Text(String(num))
                    }
                    .onAppear { print("Appeared: \(num)") }
                    .onDisappear { print("Disappeared: \(num)") }
                    .onChange(of: num) { print("Changed: \($0)") }
                }
            }
            .padding(10)
            .frame(width: 200)
            .onAppear {
                timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
                    print("Update")
                    nums = [2, 16]
                }
            }
        }
    }
}
0 Answers
Related