UPDATE: 14 months later, there is this intriguing note in the AppKit release notes:
A TextField that you are editing inside a selected List row now has correct text foreground colors. (68545878)
Now when placing a TextField in a List, the TextField becomes focused on click the very first time it is selected, but subsequent editing attempts fail: the List row is selected but the TextField does not gain focus.
O/P:
In a beta6 SwiftUI
macOS (not iOS) app, I need to have a List
with editable text fields, but the TextField
s in the list are not editable. It works fine if I swap out List
for Form
(or just VStack
), but I need it working with a List
. Is there some trick to tell the list to make the fields editable?
import SwiftUI
struct ContentView: View {
@State var stringField: String = ""
var body: some View {
List { // works if this is VStack or Form
Section(header: Text("Form Header"), footer: Text("Form Footer")) {
TextField("Line 1", text: $stringField).environment(\.isEnabled, true)
TextField("Line 2", text: $stringField)
TextField("Line 3", text: $stringField)
TextField("Line 4", text: $stringField)
TextField("Line 5", text: $stringField)
}
}
}
}
If you have configured a SwiftUI list view to support deletion or editing of its items, you can allow the user to toggle editing mode for your list view by adding an EditButton somewhere. When that is run, you'll find you can tap the edit button to enable or disable editing mode for the items in the list.
Set the Boolean variable to false, which enables editing in the text field. When someone taps the Done button, isEditing becomes false. Set the Boolean variable to true, which disables editing in the text field.
The following code is only an experiment to understand the character of List in SwiftUI and show an alternative. What I understand from observing the output from various combinations is that, List View's style is structured in a way to override the default behaviors of underlying View to become Selectable. This means that TextField does absolutely different. TextField is an focusable element where we can type. This focusing variable is not wired in to List View to work together. Hence, List override default focusable. Hence it is not possible to create List with TextView. But if you need, next best option is ScrollView instead of List and do the styling explicitly. Check the following code and both ways.
import SwiftUI
struct ContentView: View {
@State private var arr = ["1","2","3"]
var body: some View {
HStack {
VStack {
List {
ForEach(self.arr.indices, id:\.self) {
TextField("", text: self.$arr[$0])
}
}
}
.frame(minWidth: 150, maxWidth: .infinity, minHeight: 300, maxHeight: .infinity)
VStack {
ScrollView {
ForEach(self.arr.indices, id:\.self) {
TextField("", text: self.$arr[$0])
.textFieldStyle(PlainTextFieldStyle())
.padding(2)
}
}
.padding(.leading, 5)
.padding(3)
}
.background(Color(NSColor.alternatingContentBackgroundColors[0]))
.frame(minWidth: 150, maxWidth: .infinity, minHeight: 300, maxHeight: .infinity)
}
}
}
extension NSTextField {
open override var focusRingType: NSFocusRingType {
get { .none }
set { }
}
}
I updated the project to target a MacOS app and found the bug you are reporting. I've updated Apple with this feedback because it indeed does seem to be a bug (Welcome to Beta).
FB7174245 - SwiftUI Textfields embedded in a List are not editable when target is macOS
So what's the point of all the focus on state and binding below? One variable should be bound to a single control. Here is a working example. I'll leave up the older answer as it carries the example forward with a full app saving and retrieving data to/from CoreData.
import SwiftUI
struct ContentView: View {
@State var field1: String = ""
@State var field2: String = ""
@State var field3: String = ""
@State var field4: String = ""
@State var field5: String = ""
var body: some View {
List { // works if this is VStack or Form
Section(header: Text("Form Header"), footer: Text("Form Footer")) {
TextField("Line 1", text: $field1).environment(\.isEnabled, true)
TextField("Line 2", text: $field2)
TextField("Line 3", text: $field3)
TextField("Line 4", text: $field4)
TextField("Line 5", text: $field5)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
BTW - This works on Xcode Beta (11M392r) with MacOS Catalina - 10.15 Beta (19A546d).
Check out this sample that includes an editable Textfield that writes to CoreData, which I am building on Github.
Take a look at the difference between @State and @Binding so that you can manipulate data from outside of the content view. (60-sec video)
struct ContentView: View {
// 1.
@State var name: String = ""
var body: some View {
VStack {
// 2.
TextField(" Enter some text", text: $name)
.border(Color.black)
Text("Text entered:")
// 3.
Text("\(name)")
}
.padding()
.font(.title)
}
}
source
Check out the following answer for the appropriate use-case of @State (SO Answer)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With