How it works
RenameAction is a structure that triggers the rename interaction for the item a view represents, letting the system route a standard rename gesture to your own editing logic. SwiftUI supplies it through the environment so that platform affordances — a context-menu Rename command, a keyboard shortcut, or a long-press — can all begin renaming through one consistent entry point. Reach for it when a view stands in for a named, user-editable item, such as a document, folder, or list row, and you want a single place to start the rename rather than wiring up each trigger by hand. Calling the action is what hands control to the closure you registered, where you typically reveal an editable field and move focus into it.
Register the handler with renameAction(_:)
The
renameActionmodifier attaches a closure that defines what renaming means for this view and publishes aRenameActioninto the environment for descendants to invoke. Here it setsisRenaming = trueandfocused = true, the two pieces of state that swap the label for an editable field and put the cursor in it.Drive the edit surface from observable state
Because the action only flips state, the view's appearance is data-driven:
@State private var isRenamingchooses between a read-onlyText(name)and an editableTextField("Name", text: $name), while@State private var nameholds the value being renamed. The action does not touch the UI directly — it changes state, and the body reacts.Hand focus to the field with FocusState
A rename should leave the user typing immediately, so the handler also writes to a
@FocusState private var focusedbound through.focused($focused)on theTextField. Settingfocused = trueinside the closure activates the field the moment the rename begins.Commit the rename and dismiss
The same state that started the edit ends it:
.onSubmit { isRenaming = false }returns the view to its label form when the user confirms, so the rename interaction has a clear completion. The new value already lives innamevia the$namebinding.Invoke from system rename triggers
Once registered, the action backs the standard rename affordances. The
.contextMenuhere exposes aButton("Rename")that runs the identicalisRenaming = true; focused = truelogic, mirroring whatrenameActionitself begins — so menu, gesture, and shortcut all start renaming the same way.
focused = true line from the closure passed to .renameAction and trigger a rename: the TextField appears but the cursor no longer lands in it, showing exactly what the action's focus side effect contributes.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct RenameActionDemo: View {
@State private var name = "Untitled Folder"
@State private var isRenaming = false
@FocusState private var focused: Bool
var body: some View {
VStack(spacing: 16) {
if isRenaming {
TextField("Name", text: $name)
.textFieldStyle(.roundedBorder)
.focused($focused)
.onSubmit { isRenaming = false }
} else {
Text(name)
.font(.headline)
}
Text("Long-press the label to rename")
.font(.caption)
.foregroundStyle(.secondary)
}
.padding()
.contextMenu {
Button("Rename") {
isRenaming = true
focused = true
}
}
.renameAction { isRenaming = true; focused = true }
}
}