我的主 ContentView 包含一个 ChecklistView,ChecklistView 又包含几个 CheckView,CheckView 又包含一个 Toggle 视图。点击复选框时,信息会传递给 ContentViewModel,但不会返回到子视图。该如何解决这个问题?我使用的是 Xcode 16.3,Swift 5 和 Swift 6 版本没有区别。合并的代码旨在测试不同的视图声明结构。
import SwiftUI
@main
struct TestCheckListApp: App {
var body: some Scene {
WindowGroup {
ContentView(cvm: ContentViewModel())
}
}
}
import SwiftUI
final class ChecklistItem: Identifiable, ObservableObject
{
let id = UUID()
var title: String
var isChecked: Bool
init(title: String, isChecked: Bool = false) {
self.title = title
self.isChecked = isChecked
}
func toggle() { isChecked.toggle() }
}
import SwiftUI
final class ContentViewModel: ObservableObject {
@Published var report: String = ""
@Published var arrItem: [ChecklistItem] = [
ChecklistItem(title: "Item 0"),
ChecklistItem(title: "Item 1"),
ChecklistItem(title: "Item 2")
]
func buttonTapped()
{
var s: String = ""
for item in arrItem
{
s += "\(item.title) : \(item.isChecked), "
print("\(item.title) : \(item.isChecked)")
}
report = s
}
}
import SwiftUI
struct ContentView: View {
@ObservedObject var cvm: ContentViewModel
@State private var multiSelection = Set<UUID>()
var body: some View {
VStack(alignment: .leading) {
HStack {
Button(action: cvm.buttonTapped) {
Text("Display values in view model")
}
Text(cvm.report)
}
Divider()
HStack {
Text("Toggles in ContentView:")
Toggle(cvm.arrItem[0].title, isOn: $cvm.arrItem[0].isChecked)
Toggle(cvm.arrItem[1].title, isOn: $cvm.arrItem[1].isChecked)
Toggle(cvm.arrItem[2].title, isOn: $cvm.arrItem[2].isChecked)
}
Divider()
HStack {
Text("Toggles in CheckView in ContentView:")
CheckView(cli: cvm.arrItem[0])
CheckView(cli: cvm.arrItem[1])
CheckView(cli: cvm.arrItem[2])
}
Divider()
Text("Toggles in List in ContentView:")
List {
ForEach($cvm.arrItem) { item in
Toggle("item.title", isOn: item.isChecked) }
}
Divider()
Text("Toggles in ChecklistView:")
ChecklistView(cl: cvm.arrItem)
}
.padding()
.preferredColorScheme(.light)
}
}
#Preview {
ContentView(cvm: ContentViewModel())
}
import SwiftUI
struct CheckView: View {
@ObservedObject var cli: ChecklistItem
var body: some View {
Toggle(cli.title, isOn: $cli.isChecked)
}
}
#Preview {
CheckView(cli: ContentViewModel().arrItem[0])
}
import SwiftUI
struct ChecklistView : View {
var cl: [ChecklistItem]
var body: some View {
List {
ForEach(cl) { item in
CheckView(cli: item)
}
}
}
}
#Preview {
ChecklistView(cl: ContentViewModel().arrItem)
}
如果您确实想继续使用
final class ContentViewModel: ObservableObject
,请将您的 更改final class ChecklistItem
为struct ChecklistItem
,并确保在需要更改时传递绑定。此外,您还需要为您的 声明一个单一的真实数据源ContentViewModel
。示例代码,在真实设备上测试,而不是预览: