我正在构建一个应用程序,该应用程序从API获取并解码一些数据。返回的一些数据是布尔值,我希望允许用户进行切换(使用Toggle
视图)。
一旦切换,我想一个动作被执行(写回服务器)。我以前是通过onChange
修饰符来实现的,但后来我的视图层次结构中需要一组更深层次的View
对象,这导致我将@Binding属性向下传递到这些视图中。
只要我达到视图深度3,onChange
就不会被触发。我希望下面的示例代码能充分说明这个问题(我意识到使用的术语不正确,只是一个例子。
import SwiftUI
struct CPU: Hashable {
let name: String
var runners: [Runner]
}
struct Runner: Hashable {
let name: String
var isRunning: Bool
}
struct RunnersView: View {
@Binding var runners: [Runner]
var body: some View {
VStack {
ForEach($runners, id: \.self) { $runner in
Toggle(runner.name, isOn: $runner.isRunning)
}
}
.onChange(of: runners) { newValue in
print("runners changed in RunnersView:")
print(runners)
}
}
}
struct CPUView: View {
@Binding var cpu: CPU
var body: some View {
Section(cpu.name) {
RunnersView(runners: $cpu.runners)
}
.onChange(of: cpu) { newValue in
print("cpu changed in CPUView:")
print(cpu)
}
}
}
struct ContentView: View {
@State private var cpus = [
CPU(name: "CPU 1", runners: [
Runner(name: "Runner 1", isRunning: false),
Runner(name: "Runner 2", isRunning: false),
Runner(name: "Runner 3", isRunning: false),
]),
CPU(name: "CPU 2", runners: [
Runner(name: "Runner 4", isRunning: false),
Runner(name: "Runner 5", isRunning: false),
Runner(name: "Runner 6", isRunning: false),
]),
]
var body: some View {
VStack {
List($cpus, id: \.self) { $cpu in
CPUView(cpu: $cpu)
}
}
.padding()
.onChange(of: cpus, perform: { newValue in
print("cpus changed in ContentView:")
print(cpus)
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
上面的代码在切换时会触发ContentView
中的onChange
,但在其他视图中不会。
我试着仔细检查所有@Binding声明是否正确,并将一些声明更改为@State,但不可否认,我对SwiftUI相当陌生。
1条答案
按热度按时间dauxcl2d1#
你的模型结构体需要是
Identifiable
或者有一个id参数来处理ForEach
,例如。有关详细信息,请参阅docs
...集合的元素必须符合Identifiable,或者您需要为ForEach初始化器提供id参数。