Disable a Text Field in a SwiftUI List Until Tapping Edit Button
SwiftUI lists support using text fields to change the name of list items. But if your list items are navigation links, you will run into some annoying behavior on iOS. You tap a list item expecting to go to the navigation link destination, but you end up changing the name of the list item.
When you tap a list item that is a navigation link, you normally want to go to the link destination. But you still want to be able to rename list items. In SwiftUI iOS apps, you can disable the list item’s text field until someone taps the Edit button. In edit mode you can tap the list item to rename it. When the person taps the Done button, disable the text field.
Variables to Add to the SwiftUI View
Start by adding two variables to your SwiftUI view that has the list. The first variable is an environment variable for the editing mode. This variable tracks when someone taps the Edit and Done buttons.
@Environment(\.editMode) private var editMode
The second variable is a Boolean value that tracks if the text field is disabled. The name disabled
is used by SwiftUI. I got a compiler error when I named the variable disabled
so use another name for the variable.
@State private var disableTextField = true
The text field should be disabled until someone taps the Edit button.
Modifiers to Add to the Text Field
Add two modifiers to the text field. The first modifier is the .disabled
modifier. Supply the Boolean variable you added to the view.
The second modifier is the .onChange
modifier. The change you’re going to track is the change in edit mode. When someone taps the Edit button, the isEditing
property is set to true. 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.
TextField("", text: $item.name)
.disabled(disableTextField)
.onChange(of: editMode?.wrappedValue) { newValue in
if (newValue != nil) && (newValue!.isEditing) {
// Edit button tapped
disableTextField = false
}
else {
// Done button tapped
disableTextField = true
}
}
Sample Project
I have a sample project on GitHub. Look at the PageListView.swift
file in the iOS folder to see the code for disabling the text fields in the list.