SwiftUI EditMode下如何监听List的selection变量变化获取选中计数
问题原因
@State 是 SwiftUI 专属的属性包装器,它的真实存储位置独立于当前 View 结构。你自定义的 willSet/didSet 仅在你直接对 selection 变量赋值时触发,SwiftUI 通过 Binding 链路更新 @State 存储的值时会绕开这部分观察者逻辑,和 Set 插入元素的操作无关。
解决方案
以下方案均不需要自定义 EditMode:
- 方案1:使用
onChange修饰器(推荐,适配 iOS 14+、macOS 11+ 及更高版本,修改成本最低)
直接在 List 或其父视图上添加onChange监听selection的变化即可:
@State var selection = Set<UUID>() List(selection: $selection) { ForEach(items) { item in Text(item.title) } } .onChange(of: selection) { newValue in updateButtonText(count: newValue.count) }
- 方案2:通过
@Published托管状态(适配 iOS 13 等低版本系统)
把selection放到符合ObservableObject协议的视图模型中,用@Published修饰,此时不管是绑定更新还是手动赋值都会触发属性观察者:
class ListViewModel: ObservableObject { @Published var selection = Set<UUID>() { didSet { updateButtonText(count: selection.count) } } // 原有业务逻辑和 updateButtonText 实现 }
在 View 中通过 @ObservedObject 或 @StateObject 持有视图模型,绑定 selection 时使用 $viewModel.selection 即可。
- 方案3:直接依赖 SwiftUI 自动刷新(仅适用于仅需界面展示计数的场景)
如果你只需要在 UI 上展示选中数量,不需要触发额外业务逻辑,直接在界面元素中引用selection.count即可,SwiftUI 检测到状态变化会自动刷新对应 UI,无需额外监听:
Text("已选中 \(selection.count) 项")
内容的提问来源于stack exchange,提问作者sgtpotatoe
相关产品推荐
相关产品推荐

