为什么我的 SwiftUI 文本字段一次只允许更改一个字符?

Lau*_*rds 3 ios swift swiftui

我正在尝试在我的应用程序中创建特定生日/日期的视图,并且我使用了文本字段,以便用户可以更改现有的想法。但是文本字段一次只能更改一个字符?然后它会阻止用户输入(然后他们可以再次单击文本字段并更改另一个字符)。理想情况下,他们应该能够继续打字,直到他们点击停止。

这应该是所有相关的代码,因为我认为其他任何事情都不会影响它:

@State private var exampleIdeas = ["Sweets", "Chocolate", "Cake"]

ForEach($exampleIdeas, id:\.self, editActions: .delete) { $idea in
                    TextField("Idea", text: $idea)
                }
Run Code Online (Sandbox Code Playgroud)

我尝试过寻找以前的解决方案,但似乎没有其他人遇到这个问题?(我自己不知道任何可能的原因/解决方案)

Kir*_* S. 5

正如ForEach 帮助所说

\n
\n

重要的是,数据元素的 ID 不会更改,除非您用具有新标识的新数据元素替换该数据元素。如果数据元素的 ID 发生更改,从该数据元素生成的内容视图将丢失所有当前状态和动画。

\n
\n

因此,当您从 中的单词添加/更改/删除字符时TextField,您正在更改id该单词的 (因为您正在使用id:\\.self)。并且整个内容被重新生成。

\n

id您需要对, not使用其他内容self(即有一个classorstruct包含id不会更改的内容,并且您的字符串可能会更改),或者您可以有一个@Statefor 已编辑元素,并且仅在用户完成后更新原始值编辑。

\n

这是使用第一种方法的修复(修复id问题):

\n
class Idea {\n    let id = UUID() // <-- unchangeable\n    var value: String\n    \n    init(_ value: String) {\n        self.value = value\n    }\n}\n\nstruct MyView: View {\n    \n    @State private var exampleIdeas = [\n        Idea("Sweets"),\n        Idea("Chocolate"),\n        Idea("Cake")\n    ]\n    \n    var body: some View {\n            \n        VStack(spacing: 0) {\n            ForEach($exampleIdeas, \n                    id:\\.self.id, // <-- id won\'t change with editing of the value\n                    editActions: .delete) { $idea in\n                TextField("Idea", text: $idea.value)\n            }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我推荐上面的方法,因为它更简单。但这也是允许在键入时保持绑定变量完整的方法,并且仅在提交时或将焦点移动到另一个字段时更新它。在这种情况下exampleIdeas不需要更改,但我们引入了一个新的自定义 UI 组件MyTextField

\n
struct MyTextField: View {\n    \n    private let label: String\n    @State var changingText: String\n    @Binding var finalText: String\n    \n    init(_ label: String, text: Binding<String>) {\n        self.label = label\n        _finalText = text\n        changingText = text.wrappedValue\n    }\n    \n    var body: some View {\n        TextField("Idea", text: $changingText, onEditingChanged: { (changed) in\n            if !changed { // <-- changed focus to another field\n                finalText = changingText\n            }\n        })\n        .onSubmit { // <-- submitted\n            finalText = changingText\n        }\n    }\n}\n\nstruct MyView: View {\n    \n    @State private var exampleIdeas = ["Sweets", "Chocolate", "Cake"]\n    \n    var body: some View {\n            \n        VStack(spacing: 0) {\n            ForEach($exampleIdeas, id:\\.self, editActions: .delete) { $idea in\n                MyTextField("Idea", text: $idea)\n                Text(idea).italic()\n            }\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n