1

I am working with a Disclosure Group in SwiftUI. By default it displays the disclosure indicator, but it is the only thing you can tap on to display the content. I would like to be able to tap on the label 'row' to toggle the disclosure. I have set a 'sectionBindingManager' and a 'sectionBinding' function where I can set the default value (which works) to true or false, but I cannot toggle the disclosure. What am I missing?

The code:

class SectionBindingManager<T>: ObservableObject {
    private var bindings: [UUID: Binding<T>] = [:]
    private var bindingValues: [UUID: T] = [:]
    
    func binding(for id: UUID, defaultValue: T) -> Binding<T> {
        if let binding = bindings[id] {
            return binding
        } else {
            bindingValues[id] = defaultValue
            let newBinding = Binding<T> {
                return self.bindingValues[id] ?? defaultValue
            } set: { value in
                self.bindingValues[id] = value
            }
            bindings[id] = newBinding
            return newBinding
        }
    }
}

...

struct CuisineListView: View {
    
    // MARK: - Properties
    @EnvironmentObject var dataController: DataController
    @EnvironmentObject var sectionBindingManager: SectionBindingManager<Bool>
    ...

private func sectionBinding(for id: UUID?) -> Binding<Bool> {
    guard let id = id else {
        return Binding<Bool> {
            return true
        } set: { value in
            return
        }
    }
    return sectionBindingManager.binding(for: id, defaultValue: false)
}

...

var body: some View {
    Group {
        List {
            ForEach(cuisines, id: \.id) { cuisine in
                DisclosureGroup(isExpanded: sectionBinding(for: cuisine.id)) {
                    ForEach(cuisine.sortedDishTypes(), id: \.id) { dishType in
                        NavigationLink(destination: RecipeListView(cuisine: cuisine, selectedDishType: dishType)) {
                            Text(dishType.name!)
                                .padding(.leading, 20)
                        }
                    }
                } label: {
                    // Header
                    HStack {
                        Image(cuisine.icon ?? "North American")
                            .resizable()
                            .scaledToFit()
                            .frame(width: 24, height: 24)
                        Text(cuisine.name!)
                            .font(.headline)
                            .fontWeight(.semibold)
                            .padding(.leading, 5)
                        Spacer()
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        withAnimation {
                            isExpanded.toggle()
                        }
                    }
                }
            } //: LOOP

            ...
forrest
  • 10,570
  • 25
  • 70
  • 132
  • 1
    Does this answer your question https://stackoverflow.com/a/63228810/12299030? – Asperi Oct 21 '21 at 18:59
  • It is very suspicious that `SectionBindingManager` conforms to `ObservableObject`, but has no `@Published` properties and doesn't manually call `objectWillChange.send()`. There is no way for SwiftUI to know when `bindingValues` has changed. – rob mayoff Oct 21 '21 at 19:20
  • @Asperi thank you very much. That fixed the problem and I was able to remove all of the attempts at Binding. – forrest Oct 21 '21 at 19:28

0 Answers0