本文介绍了列表中的 SwiftUI 文本字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个包含行的列表,每行中有 2 个文本字段.这些行应该保存在一个数组中,这样我就可以在另一个视图中使用这些数据来实现进一步的功能.如果 Textfield 中的文本发生更改,则该文本应保存在数组的右侧条目中.您还可以通过按钮将新行添加到列表中,这也应该更改行的数组.

I want a list with rows, with each row having 2 Textfields inside of it. Those rows should be saved in an array, so that I can use the data in an other view for further functions. If the text in the Textfield is changed, the text should be saved inside the right entry in the array.You also can add new rows to the list via a button, which should also change the array for the rows.

目标是有一个键值对列表,每个键值对都可编辑,并且这些条目与当前文本一起保存.

The goal is to have a list of key value pairs, each one editable and those entries getting saved with the current text.

有人可以帮助我和/或提示我解决这个问题吗?

Could someone help me and/or give me hint for fixing this problem?

到目前为止,我已经尝试过这样的事情:

So far I have tried something like this:

// the array of list entries
@State var list: [KeyValue] = [KeyValue()]
// the List inside of a VStack
List(list) { entry in
    KeyValueRow(list.$key, list.$value)
}
// the single item
struct KeyValue: Identifiable {
    var id = UUID()

    @State var key = ""
    @State var value = ""
}
// one row in the list with view elements
struct KeyValueRow: View {

    var keyBinding: Binding<String>
    var valueBinding: Binding<String>

    init(_ keyBinding: Binding<String>, _ valueBinding: Binding<String>){
        self.keyBinding = keyBinding
        self.valueBinding = valueBinding
    }

    var body: some View {
        HStack() {
            TextField("key", text: keyBinding)
            Spacer()
            TextField("value", text: valueBinding)
            Spacer()
        }
    }
}

另外,关于添加新条目的按钮.问题是,如果我执行以下操作,我在视图中的列表变为空白,一切又变为空(可能相关:ListView 中的 SwiftUI TextField 过滤后变为空白列表项 ?)

Also, about the button for adding new entries.Problem is that if I do the following, my list in the view goes blank and everything is empty again(maybe related: SwiftUI TextField inside ListView goes blank after filtering list items ?)

Button("Add", action: {
    self.list.append(KeyValue())
})

推荐答案

我不确定最好的做法是在像这样的数组中保持视图的状态是最新的,但这里有一种方法可以使其工作.

I am not sure what the best practice is keep a view up to date with state in an array like this, but here is one approach to make it work.

对于模型,我添加了一个符合 Observable 对象的列表类,每个 KeyValue 项都会在发生变化时提醒它:

For the models, I added a list class that conforms to Observable object, and each KeyValue item alerts it on changes:

class KeyValueList: ObservableObject {

    @Published var items = [KeyValue]()

    func update() {
        self.objectWillChange.send()
    }

    func addItem() {
        self.items.append(KeyValue(parent: self))
    }
}
class KeyValue: Identifiable {

    init(parent: KeyValueList) {
        self.parent = parent
    }

    let id = UUID()
    private let parent: KeyValueList

    var key = "" {
        didSet { self.parent.update() }
    }
    var value = "" {
        didSet { self.parent.update() }
    }
}

然后我可以简单地将行视图保留一个状态:

Then I was able to simply the row view to just keep a single piece of state:

struct KeyValueRow: View {

    @State var item: KeyValue

    var body: some View {
        HStack() {
            TextField("key", text: $item.key)
            Spacer()
            TextField("value", text: $item.value)
            Spacer()
        }
    }
}

对于列表视图:

struct TextFieldList: View {

    @ObservedObject var list = KeyValueList()

    var body: some View {

        VStack {
            List(list.items) { item in
                HStack {
                    KeyValueRow(item: item)
                    Text(item.key)
                }
            }
            Button("Add", action: {
                self.list.addItem()
            })

        }
    }
}

我只是在其中添加了一个额外的 Text 以进行测试以查看它是否实时更新.

I just threw an extra Text in there for testing to see it update live.

我没有像您描述的那样遇到使视图消隐的添加"按钮.这是否也为您解决了这个问题?

I did not run into the Add button blanking the view as you described. Does this solve that issue for you as well?

这篇关于列表中的 SwiftUI 文本字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 05:43