Skip to main content

How to detect and respond to key press events

About 2 minSwiftSwiftUIArticle(s)bloghackingwithswift.comcrashcourseswiftswiftuixcodeappstore

How to detect and respond to key press events 관련

SwiftUI by Example

Back to Home

How to detect and respond to key press events | SwiftUI by Example

How to detect and respond to key press events

Updated for Xcode 15

New in iOS 17

SwiftUI has an onKeyPress() modifier that lets us respond to hardware keyboard events being triggered in our app, with the only catch being that the view where you're watching for key presses must currently have input focus.

Watching for key presses takes various forms depending on what you want, but no matter what approach you take your view must be focusable in order to respond to a key press. So, this code marks a Text view as being focusable and currently focused, then updates its contents whenever a key is pressed:

struct ContentView: View {
    @FocusState private var focused: Bool
    @State private var key = ""

    var body: some View {
        Text(key)
            .focusable()
            .focused($focused)
            .onKeyPress { press in
                key += press.characters
                return .handled
            }
            .onAppear {
                focused = true
            }
    }
}

Download this as an Xcode projectopen in new window

The message typing is fun being typed out one letter at a time.
The message typing is fun being typed out one letter at a time.

The return .handled part tells SwiftUI the key press has been responded to in full by our action closure. If you send back .ignored instead, the key press will be passed on to whatever parent view is able to handle it next.

Note

The characters we receive do not have any modifier keys attached, so it won't give you things like uppercase letters or special symbols.

Other forms of onKeyPress() include one to track which phase was triggered, so you could use this code to track only when a key has been released:

Text(key)
    .onKeyPress(phases: .up) { press in
        print("Received \(press.characters)")
        return .handled
    }

There's a variant that responds only to certain kinds of keys being pressed:

Text(key)
    .onKeyPress(characters: .alphanumerics) { press in
        print("Received \(press.characters)")
        return .handled
    }

And there's even a variant that responds to specific characters being pressed, provided either as a list of built-in constants or characters. So, this will listen for people frantically mashing keys to quit Vim:

Text(key)
    .onKeyPress(keys: [.escape, "w", "q"]) { press in
        print("Received \(press.characters)")
        return .handled
    }
Similar solutions…
How to respond to view lifecycle events: onAppear() and onDisappear() | SwiftUI by Example

How to respond to view lifecycle events: onAppear() and onDisappear()
SwiftUI tips and tricks | SwiftUI by Example

SwiftUI tips and tricks
All SwiftUI property wrappers explained and compared | SwiftUI by Example

All SwiftUI property wrappers explained and compared
How to detect the user hovering over a view | SwiftUI by Example

How to detect the user hovering over a view
How to detect the location of a tap inside a view | SwiftUI by Example

How to detect the location of a tap inside a view

이찬희 (MarkiiimarK)
Never Stop Learning.