What's wrong with the List in debug mode on Xcode 16? And partly in the release mode.

When building in Xcode 15.4 debug, only a part of the initial View for List is initialized. As you scroll, new ones are initialized, and old ones are destroyed.

When building the same code in Xcode 16.2, ALL Views are initialized first, and then immediately destroyed as you scroll, new ones are initialized, and old ones are destroyed.

MRE:

struct ContentView: View {
    private let arr = Array(1...5555)

    var body: some View {
        List(arr, id: \.self) {
            ListCellView(number: $0)
        }
    }
}

struct ListCellView: View {
    private let number: Int
    private let arr: [Int]
    @StateObject private var vm: ListCellViewModel // Just to print init/deinit

    init(number: Int) {
        print(#function, Self.self, number)
        self.arr = Array(0...number)
        self.number = number
        let vm = ListCellViewModel(number: number) // To see duplicates of init
        self._vm = StateObject(wrappedValue: vm) // because here is @autoclosure
    }

    var body: some View {
        let _ = print(#function, Self.self, number)
        Text("\(number)")
    }
}

class ListCellViewModel: ObservableObject {
    private let number: Int

    init(number: Int) {
        print(#function, Self.self, number)
        self.number = number
    }

    deinit {
        print(#function, Self.self, number)
    }
}

An example from a memory report with this code:

Fortunately, the behavior in release mode is the same as in Xcode 15.4. However, the double initialization of Views is still present and has not been fixed.

...
init(number:) ListCellView 42
init(number:) ListCellViewModel 42
init(number:) ListCellView 42
init(number:) ListCellViewModel 42
deinit ListCellViewModel 42
body ListCellView 42

Yes, unnecessary View initializations and extra body calls are "normal" for SwiftUI, but why do they here twice so that one is discarded immediately?

What's wrong with the List in debug mode on Xcode 16? And partly in the release mode.
 
 
Q