SwiftUI中如何为DisclosureGroup内的Google Task任务绑定checked属性的引用
解决SwiftUI中Toggle绑定Google Task独立勾选状态的问题
你遇到的核心问题是所有Toggle共享了同一个@State变量,导致修改一个任务的勾选状态会同步到所有任务。要实现每个任务独立的勾选状态,我们需要让每个Toggle直接绑定对应GoogleTask实例的checked属性,同时确保SwiftUI能感知到属性变化并更新视图。
解决方案步骤:
1. 让GoogleTask遵循ObservableObject并标记checked为@Published
因为GoogleTask是类(引用类型),我们需要让它成为可观察对象,这样当checked属性变化时,SwiftUI能自动刷新对应的视图:
class GoogleTask: Identifiable, Equatable, ObservableObject { static func == (lhs: GoogleTask, rhs: GoogleTask) -> Bool { lhs.id == rhs.id } let name: String @Published var checked = false // 标记为@Published,让属性变化可被观察 let id = UUID() init(name: String) { self.name = name } }
2. 修改ContentView,为每个任务创建独立绑定
在遍历任务时,将task声明为@ObservedObject,这样就能直接绑定它的checked属性,每个Toggle都会对应唯一的任务状态:
struct ContentView: View { @ObservedObject var viewModel = TaskList() // 移除全局的@State var checked,不需要共享状态了 var body: some View { List { ForEach(viewModel.tasklists) { tasklist in DisclosureGroup(tasklist.name) { // 将task声明为@ObservedObject,监听它的属性变化 ForEach(tasklist.tasks ?? []) { @ObservedObject var task in Toggle(task.name, isOn: $task.checked) } } } } .padding() } }
补充说明:
- 如果不想让
GoogleTask遵循ObservableObject,也可以通过手动创建Binding来实现,但这种方式不会自动刷新视图(除非你手动触发视图更新):
但更推荐第一种方式,因为它能自动处理视图更新,代码也更简洁。Toggle(task.name, isOn: Binding( get: { task.checked }, set: { task.checked = $0 } )) - 你的
TaskList和GoogleTasklist模型不需要修改,保持现有结构即可,因为TaskList已经是ObservableObject,tasklists数组的变化会被正确监听。
这样修改后,每个Toggle都会独立绑定对应任务的checked属性,勾选状态再也不会同步,而且修改状态时视图会自动刷新。
内容的提问来源于stack exchange,提问作者Money
相关产品推荐
相关产品推荐

