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.

Get the Swift Dev Journal Newsletter

Subscribe and get exclusive articles, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

    We won't send you spam. Unsubscribe at any time.