Section Does Not Seem To Expand/Collapse

This is obviously a user error, but I've been working on different possibilities for a couple of days and nothing works. The problem is my Section in the following code doesn't expand or collapse when I click on the chevron:

`class AstroCat { var title: String var contents: [ String ] var isExpanded: Bool

init(title: String, contents: [String], isExpanded: Bool) {
    self.title = title
    self.contents = contents
    self.isExpanded = isExpanded
}

}

struct TestView: View {

@Binding var isShowingTargetSelection: Bool
@State var catalog: AstroCat
@State private var expanded = false

var body: some View {
    NavigationStack {
        List {
            Section(catalog.title, isExpanded: $catalog.isExpanded) {
                ForEach(catalog.contents, id: \.self) { object in
                    Text(object)
                }
            }
        }
        .navigationTitle("Target")
        .listStyle(.sidebar)
    }
}

}

#Preview {

struct TestPreviewContainer : View {
    @State private var value = false
    @State var catalog = AstroCat(title: "Solar System", contents: ["Sun", "Mercury", "Venus", "Earth"], isExpanded: true)

    var body: some View {
       TestView(isShowingTargetSelection: $value, catalog: catalog)
    }
}

return TestPreviewContainer()

}`

If I change the "isExpanded: $catalog.isExpanded" to just use the local variable "expanded", then it works, so I think I have the basic SwiftUI pieces correct. But using a boolean inside of the class doesn't seem to work (the section just remains expanded or collapsed based on the initial value of the class variable).

Any hints? Am I not specifying the binding correctly? (I've tried a bunch of alternatives)

Thanks for the help, Robert

The problem here is that your data model is a class. The @State property wrapper is primarily designed to work with value types (like struct and enum). When you assign a new value to a @State variable, SwiftUI can see that the entire value has changed and re-renders the view. But with a class, the reference stays the same when you just change its properties, so SwiftUI doesn't notice and doesn't update the view.

However, that doesn't mean you can't use classes at all. The Observation framework allows a class to expose properties that, when changed, will cause the view to update.

So, you have two options:

  1. Change your data model to a struct.
  2. Add the @Observable macro to your data model.

Interesting, I had not considered that. Makes sense.

But ... doesn't it seem like the compiler or runtime would at least give me a warning that using @State with a class has the problem you described? Or is there a case where @State with a class is the right thing to do?

Robert

Section Does Not Seem To Expand/Collapse
 
 
Q