You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI如何实现点击整个DisclosureGroup Label行切换展开状态

问题原因与修复方案

1. 状态变更无法触发视图刷新

你定义的SectionBindingManager虽然遵守了ObservableObject协议,但存储展开状态的bindingValues属性没有添加@Published标记,值修改时不会向订阅的视图发送更新通知,因此看不到展开状态的变化。

2. 点击事件未正确操作绑定值

你在label的onTapGesture中直接调用isExpanded.toggle(),但当前作用域并没有定义isExpanded变量,需要先拿到当前菜系对应的展开状态绑定再进行操作。


修正代码

修正SectionBindingManager

class SectionBindingManager<T>: ObservableObject {
    // 新增@Published标记,状态变更时自动通知视图
    @Published private var bindingValues: [UUID: T] = [:]
    
    func binding(for id: UUID, defaultValue: T) -> Binding<T> {
        Binding<T> {
            return self.bindingValues[id] ?? defaultValue
        } set: { value in
            self.bindingValues[id] = value
        }
    }
}

这里去掉了不必要的bindings缓存,每次直接生成绑定即可,避免缓存导致的状态不同步问题。

修正列表部分代码

ForEach(cuisines, id: \.id) { cuisine in
    // 先拿到当前菜系对应的展开状态绑定
    let isExpanded = sectionBinding(for: cuisine.id)
    DisclosureGroup(isExpanded: isExpanded) {
        ForEach(cuisine.sortedDishTypes(), id: \.id) { dishType in
            NavigationLink(destination: RecipeListView(cuisine: cuisine, selectedDishType: dishType)) {
                Text(dishType.name!)
                    .padding(.leading, 20)
            }
        }
    } label: {
        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.wrappedValue.toggle()
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者forrest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 07:36:08