我在这里查看了不同的问题,但不幸的是我找不到答案。这是我的代码:
SceneDelegate.swift
...
let contentView = ContentView(elementHolder: ElementHolder(elements: ["abc", "cde", "efg"]))
...
window.rootViewController = UIHostingController(rootView: contentView)
ContentView.swift
class ElementHolder: ObservableObject {
@Published var elements: [String]
init(elements: [String]) {
self.elements = elements
}
}
struct ContentView: View {
@ObservedObject var elementHolder: ElementHolder
var body: some View {
VStack {
ForEach(self.elementHolder.elements.indices, id: \.self) { index in
SecondView(elementHolder: self.elementHolder, index: index)
}
}
}
}
struct SecondView: View {
@ObservedObject var elementHolder: ElementHolder
var index: Int
var body: some View {
HStack {
TextField("...", text: self.$elementHolder.elements[self.index])
Button(action: {
self.elementHolder.elements.remove(at: self.index)
}) {
Text("delete")
}
}
}
}
当按下删除按钮时,应用程序因索引越界错误而崩溃。
有两个奇怪的事情,应用程序在运行时
1) 删除
VStack
并将 ForEach
放入 body
的 ContentView.swift
或2)你把
SecondView
的代码直接放到ForEach
中只是一件事:我真的需要
ObservableObject
,这段代码只是另一个代码的简化。更新
我更新了我的代码并将
Text
更改为 TextField
,因为我不能只传递一个字符串,我需要双向连接。
最佳答案
这是可能的解决方案 - 使 SecondView
的主体不依赖 ObservableObject
。
使用 Xcode 11.4/iOS 13.4 测试 - 没有崩溃
struct SecondView: View {
@ObservedObject var elementHolder: ElementHolder
var index: Int
let value: String
init(elementHolder: ElementHolder, index: Int) {
self.elementHolder = elementHolder
self.index = index
self.value = elementHolder.elements[index]
}
var body: some View {
HStack {
Text(value) // not refreshed on delete
Button(action: {
self.elementHolder.elements.remove(at: self.index)
}) {
Text("delete")
}
}
}
}
另一个可能的解决方案是不要在
ElementHolder
中观察 SecondView
... 不需要显示和删除它 - 也没有崩溃struct SecondView: View {
var elementHolder: ElementHolder // just reference
var index: Int
var body: some View {
HStack {
Text(self.elementHolder.elements[self.index])
Button(action: {
self.elementHolder.elements.remove(at: self.index)
}) {
Text("delete")
}
}
}
}
更新: 文本字段的
SecondView
变体(仅更改文本字段本身)struct SecondViewA: View {
var elementHolder: ElementHolder
var index: Int
var body: some View {
HStack {
TextField("", text: Binding(get: { self.elementHolder.elements[self.index] },
set: { self.elementHolder.elements[self.index] = $0 } ))
Button(action: {
self.elementHolder.elements.remove(at: self.index)
}) {
Text("delete")
}
}
}
}
关于在 ForEach 中删除数组元素时,SwiftUI 没有索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61430999/