Reputation: 1768
I try to have a list of editable strings and deletable strings that come from a string array.
struct ShortcutSettingView: View {
@State var keywords: [String] = ["keyword 1", "keyword 2", "keyword 3"]
var body: some View {
Form {
List {
ForEach(keywords, id: \.self) { keyword in
TextField("", text: $keywords[keywords.firstIndex(of: keyword)!)
}
.onDelete(perform: deleteKeywords)
}
}
.navigationTitle(Text("Generic Shortcut"))
}
private func deleteKeywords(_ offsets: IndexSet) {
keywords.remove(atOffsets: offsets)
}
}
I tried the following but I run into the following two issues:
TextField
s (I assume this is caused by a refresh of the view)I could fix #2 with the following update
TextField("", text: Binding<String>(get: {keywords[keywords.firstIndex(of: keyword)!] ?? "<error>"}, set: {keywords[keywords.firstIndex(of: keyword)] = $0}))
But the textfields are still not usable as intended because of the disappearing keyboard issue (#1).
Upvotes: 0
Views: 217
Reputation: 581
Each time the user edit a TextField, you modify the content of the keywords variable. Because your text field are created depending on that list, they hence get refreshed. They are all deleted and recreated again so the user can't continue to edit.
Your second problem is due to the fact that your keyword array is edited by the user. You thus need to manage delete entries.
The solution is to not create your text field directly based on what's inside the list, but based on the length of the list. Replace your for each like so and your first problem is solved :
ForEach(0..<keywords.count, id: \.self) { index in
TextField("", text: $keywords[index])
}
Then to solve your second problem we have to change the part of the text field which retrieve the content. We make it use proxy binding :
TextField("", text: Binding(
get: { keywords[index] },
set: { keywords[index] = $0 }))
Your final code should look like :
ForEach(0..<keywords.count, id: \.self) { index in
TextField("", text: Binding(
get: { keywords[index] },
set: { keywords[index] = $0 }))
}
.onDelete(perform: deleteKeywords)
Upvotes: 2