gpt4 book ai didi

swift - SwiftUI 上带有 TextField 的可删除表

转载 作者:行者123 更新时间:2023-12-03 09:23:51 26 4
gpt4 key购买 nike

环境

  • Xcode 11.2.1 (11B500)

  • 问题

    为了在 SwiftUI 上使用 TextField 实现可编辑的 teble,我使用了 ForEach(0..<items.count)处理索引。

    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])
    }
    }
    }
    }

    但是,如果将表更改为可删除,则会出现问题。

    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
    }
    }
    }
    }

    Thread 1: Fatal error: Index out of range when delete item

    🐶 已从动物中删除,并且 ForEach 循环似乎运行了两次,即使 animals.count 为 1。
    (lldb) po animals.count
    1

    (lldb) po animals
    ▿ 1 element
    - 0 : "🐱"

    请给我关于 Foreach 和 TextField 组合的建议。
    谢谢。

    最佳答案

    好的,原因在于使用的 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)
    所以解决方案是提供动态容器。您可以在下面找到可能的方法的演示。
    完整模块代码
    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
    })
    }
    }
    backup

    关于swift - SwiftUI 上带有 TextField 的可删除表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58909773/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com