TechnologiesSwiftUIToolbars and Commands

KeyPress struct

iOSmacOStvOSwatchOSvisionOS✓ renders

A structure that describes a key press event received by a view.

How it works

KeyPress is the value SwiftUI hands you each time a focused view receives keyboard input, packaging the pressed key together with its modifiers and the phase of the event. Reach for it when you want a view to respond to hardware keyboard activity directly — arrow-key navigation, shortcut letters, Return to confirm — rather than relying on a text field or a menu command. Because it arrives as a structured value, you inspect its properties to decide whether a given key concerns you, and report back whether you consumed the event.

  1. Make the view eligible for key input with focusable()

    Key presses are only delivered to a view that can hold keyboard focus, so the view must opt in before any KeyPress arrives. Here .focusable() marks the input surface, establishing the focus target that the keyboard events flow to.

  2. Receive each event in the onKeyPress closure

    The onKeyPress modifier installs a handler whose closure is called with a single KeyPress value for every qualifying key event. In the example the parameter is named and typed explicitly, (press: KeyPress), giving you a fresh value to examine on each keystroke.

  3. Read the pressed key through the key property

    KeyPress exposes the physical key via its key property, a KeyEquivalent that carries the actual character produced. The example reads press.key.character to build its display string, which is how arrow keys, Return, and letters all surface through the same value.

  4. Report the outcome with KeyPress.Result

    The closure must return a KeyPress.Result so SwiftUI knows whether the event was consumed or should keep propagating. Returning .handled tells the system you dealt with this press; returning .ignored would let it pass on to other responders.

Try it — Change the returned value from .handled to .ignored and observe that, while lastKey still updates, the key press now also flows on to the rest of the responder chain instead of being consumed here.

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.

KeyPress.swift
struct KeyPressDemo: View {
    @State private var lastKey = "Press any key"

    var body: some View {
        VStack(spacing: 12) {
            Text("Keyboard Input")
                .font(.headline)
            Text(lastKey)
                .font(.title2.monospaced())
                .foregroundStyle(.tint)
            Text("Try arrow keys, return, or letters")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .padding()
        .focusable()
        .onKeyPress { (press: KeyPress) in
            lastKey = "Key: \(press.key.character)"
            return .handled
        }
    }
}
Live preview
Keyboard Input Press any key Try arrow keys, return, or letters
Keyboard Input Press any key Try arrow keys, return, or letters
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →