为了在 SwiftUI 上使用 TextField 实现可编辑的 teble,我曾经ForEach(0..<items.count)处理过index.html 。
import SwiftUI
struct DummyView: View {
@State var animals: [String] = ["", ""]
var body: some View {
List {
EditButton()
ForEach(0..<animals.count) { i in
TextField("", text: self.$animals[i])
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果将表更改为可删除,则会出现问题。
import SwiftUI
struct DummyView: View {
@State var animals: [String] = ["", ""]
var body: some View {
List {
EditButton()
ForEach(0..<animals.count) { i in
TextField("", text: self.$animals[i]) // Thread 1: Fatal error: Index out of range
}
.onDelete { indexSet in
self.animals.remove(atOffsets: indexSet) // Delete "" from animals
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Thread 1: Fatal error: Index out of range 删除项目时
已从动物中删除并且 ForEach 循环似乎运行了两次,即使 Animal.count 为 1。
(lldb) po animals.count
1
(lldb) po animals
? 1 element
- 0 : ""
Run Code Online (Sandbox Code Playgroud)
请给我关于 Foreach 和 TextField 组合的建议。
谢谢。
Asp*_*eri 10
好的,原因在已使用的 ForEach 构造函数的文档中(如您所见,范围是恒定的,因此 ForEach 获取初始范围并保持它):
/// Creates an instance that computes views on demand over a *constant*
/// range.
///
/// This instance only reads the initial value of `data` and so it does not
/// need to identify views across updates.
///
/// To compute views on demand over a dynamic range use
/// `ForEach(_:id:content:)`.
public init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)
Run Code Online (Sandbox Code Playgroud)
所以解决方案是提供动态容器。您可以在下面找到可能方法的演示。
完整的模块代码
import SwiftUI
struct DummyView: View {
@State var animals: [String] = ["", ""]
var body: some View {
VStack {
HStack {
EditButton()
Button(action: { self.animals.append("Animal \(self.animals.count + 1)") }, label: {Text("Add")})
}
List {
ForEach(animals, id: \.self) { item in
EditorView(container: self.$animals, index: self.animals.firstIndex(of: item)!, text: item)
}
.onDelete { indexSet in
self.animals.remove(atOffsets: indexSet) // Delete "" from animals
}
}
}
}
}
struct EditorView : View {
var container: Binding<[String]>
var index: Int
@State var text: String
var body: some View {
TextField("", text: self.$text, onCommit: {
self.container.wrappedValue[self.index] = self.text
})
}
}
struct TestForEachCapture_Previews: PreviewProvider {
static var previews: some View {
DummyView()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1211 次 |
| 最近记录: |