recursionviewswiftuiupdatesdisclosure

I use disclousreGroup as recursion, but the view update doesn't work properly. Is there any way?


enter image description here

If you change the data after collapse, the View is reused and drawn strangely.

Reusing the View in swiftUI seems to produce these results.

Can I control the reuse of Views? Or is there another way?

Is it related to id?

Below is the code:

import SwiftUI

@main
struct TestApp: App {
    var item: Item = dummyItems
    var item2: Item = dummyItems2

    @State var isChange: Bool = true
    
    var body: some Scene {
        WindowGroup {
            VStack {
                List {
                    if isChange {
                        ContentView(item: item)
                    } else {
                        ContentView(item: item2)

                    }
                }
                Button("change") {
                    isChange.toggle()
                }
            }
        }
    }
}

import SwiftUI

struct ContentView: View {
    let item: Item
    
    init(item: Item) {
        self.item = item
    }
    
    var body: some View {
        ForEach(item.children) { item in
            if item.children.isEmpty {
                Text("\(item.title)")
            } else {
                DisclosureGroup(
                    isExpanded: item.$isExpanded,
                    content: {
                        ContentView(item: item)
                    },
                    label: { Text("\(item.title)") }
                )
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    
    static var previews: some View {
        let item: Item = dummyItems
        ContentView(item: item)
    }
}

struct Item: Identifiable {
    var id: UUID = UUID()
    
    @Binding var isExpanded: Bool
    var title: String = "title"
    var children: [Item] = []
    
    init(title: String,
         children: [Item]) {
        self.title = title
        self.children = children
        self._isExpanded = .constant(true)
    }
}

let dummyItems2 = Item(title: "root",
                      children: [
                        Item(title: "1",
                             children: [
                                Item(title: "1-1",
                                     children: [
                                        Item(title: "1-1-1",
                                             children: [])]
                                ),
                                Item(title: "1-2",
                                     children: [
                                        Item(title: "1-2-1",
                                             children: []),
                                        Item(title: "1-2-2",
                                             children: [])]
                                )
                             ]),
                        Item(title: "2",
                             children: [
                                Item(title: "2-1",
                                     children: [
                                        Item(title: "2-1-1",
                                             children: [])]
                                ),
                                Item(title: "2-2",
                                     children: [
                                        Item(title: "2-2-1",
                                             children: [])]
                                ),
                                Item(title: "2-3",
                                     children: [
                                        Item(title: "2-3-1",
                                             children: [])]
                                ),
                             ]),
                        Item(title: "3",
                             children: [
                                Item(title: "3-1",
                                     children: [
                                        Item(title: "3-1-1",
                                             children: []),
                                        Item(title: "3-1-2",
                                             children: []),
                                        Item(title: "3-1-3",
                                             children: [])]
                                ),
                                Item(title: "3-2",
                                     children: [
                                        Item(title: "3-1-1",
                                             children: [])]
                                ),
                                Item(title: "3-3",
                                     children: [
                                        Item(title: "3-1-1",
                                             children: [])]
                                )
                             ])
                        
                      ])



let dummyItems = Item(title: "root",
                      children: [
                        Item(title: "1",
                             children: [
                                Item(title: "1-1",
                                     children: [
                                        Item(title: "1-1-1",
                                             children: [])]
                                ),
                                Item(title: "1-2",
                                     children: [
                                        Item(title: "1-2-1",
                                             children: []),
                                        Item(title: "1-2-2",
                                             children: [])]
                                )
                             ]),
                        Item(title: "2",
                             children: [
                                Item(title: "2-1",
                                     children: [
                                        Item(title: "2-1-1",
                                             children: [])]
                                ),
                             ]),
                        Item(title: "3",
                             children: [
                                Item(title: "3-1",
                                     children: [
                                        Item(title: "3-1-1",
                                             children: []),
                                        Item(title: "3-1-2",
                                             children: []),
                                        Item(title: "3-1-3",
                                             children: [])]
                                ),
                                Item(title: "3-2",
                                     children: [
                                        Item(title: "3-1-1",
                                             children: [])]
                                ),
                                Item(title: "3-3",
                                     children: [
                                        Item(title: "3-1-1",
                                             children: [])]
                                )
                             ])
                        
                      ])

Solution

  • Try the following

    List {
        if isChange {
            ContentView(item: item)
        } else {
            ContentView(item: item2)
    
        }
    }
    .id(isChange)    // << here !!