为什么运行此代码会显示“致命错误:索引超出范围”?
import SwiftUI
struct MyData {
var numbers = [Int](repeating: 0, count: 5)
}
@main
struct TrySwiftApp: App {
@State var myData = MyData()
var body: some Scene {
WindowGroup {
ChildView(myData: myData)
.frame(width: 100, height: 100)
.onAppear {
myData.numbers.removeFirst() // change myData
}
}
}
}
struct ChildView: View {
let myData: MyData // a constant
var body: some View {
ForEach(myData.numbers.indices) {
Text("\(myData.numbers[$0])") // Thread 1: Fatal error: Index out of range
}
}
}
Run Code Online (Sandbox Code Playgroud)
检查其他问题后,我知道我可以通过以下方式修复它
// fix 1: add id
ForEach(myData.numbers.indices, id: \.self) {
//...
}
Run Code Online (Sandbox Code Playgroud)
或者
// Edited:
//
// This is not a fix, see George's reply
//
// fix 2: make ChildView conforms to Equatable
struct ChildView: View, Equatable {
static func == (lhs: ChildView, rhs: ChildView) -> Bool {
rhs.myData.numbers == rhs.myData.numbers
}
...
Run Code Online (Sandbox Code Playgroud)
我的问题:
常量值
(由 let 定义)
如何不同步?
ForEach 到底做了什么?
让我举一个简单的例子来告诉你发生了什么:
struct ContentView: View {
@State private var lowerBound: Int = 0
var body: some View {
ForEach(lowerBound..<11) { index in
Text(String(describing: index))
}
Button("update") { lowerBound = 5 }.padding()
}
}
Run Code Online (Sandbox Code Playgroud)
如果你看上面的代码,你会发现我正在用这样的 Range 初始化 ForEach:lowerBound..<11这意味着这个0..<11,当你这样做时,你是在告诉 SwiftUI,嘿,这是我的范围,它不会改变!这是一个恒定的范围!SwiftUI 说可以!如果您不打算更新上限或下限,您可以使用 ForEach 而不显示或给出id!但如果你再次看到我的代码!我正在更新 ForEach 的 lowerBound,通过此操作,我打破了关于恒定范围的协议!所以 SwiftUI 来告诉我们,如果你要更新我的 ForEach 范围的计数或任何东西,那么你必须使用 anid然后你可以更新给定的范围!原因是因为如果我们有 2 个具有相同值的相同项目,SwiftUI 将无法知道您说的是哪一个!通过使用id我们正在解决 SwiftUI 的识别问题!关于 id 你可以像这样使用它:或者如果你的结构符合可哈希协议,那么你可以id:\.self像这样使用它,或者在最后一种情况下,如果你的结构符合可识别协议,你可以停止使用 id!id:\.customID那么 ForEach 就会神奇地随之沉没。
现在看看编辑后的代码,它将构建并运行,因为我们解决了识别问题:
struct ContentView: View {
@State private var lowerBound: Int = 0
var body: some View {
ForEach(lowerBound..<11, id:\.self) { index in
Text(String(describing: index))
}
Button("update") { lowerBound = 5 }.padding()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3260 次 |
| 最近记录: |