Skip to content

Instantly share code, notes, and snippets.

@chipjarred
Last active June 2, 2023 18:52
Show Gist options
  • Save chipjarred/e39c48619e591fbf9588af3d3684bed9 to your computer and use it in GitHub Desktop.
Save chipjarred/e39c48619e591fbf9588af3d3684bed9 to your computer and use it in GitHub Desktop.
Detecting keyboard state in SwiftUI
import SwiftUI
extension CGKeyCode
{
// Define whatever key codes you want to detect here
static let kVK_Space: CGKeyCode = 0x31
var isPressed: Bool {
CGEventSource.keyState(.combinedSessionState, key: self)
}
}
class SpaceDetector: ObservableObject {
@Published var isPressed: Bool = false
}
class KeyboardManager {
static let spaceDetector = SpaceDetector()
private static let pollingInterval: DispatchTimeInterval = .milliseconds(50)
private static let pollingQueue = DispatchQueue.main
static func start() {
scheduleNextPoll(on: pollingQueue)
}
static var keyStates: [CGKeyCode: Bool] = [
.kVK_Space: false,
// populate with other key codes you're interested in
]
static func dispatchKeyDown(_ key: CGKeyCode)
{
if key == .kVK_Space {
spaceDetector.isPressed = true
}
}
static func dispatchKeyUp(_ key: CGKeyCode) {
if key == .kVK_Space {
spaceDetector.isPressed = false
}
}
private static func scheduleNextPoll(on queue: DispatchQueue) {
queue.asyncAfter(deadline: .now() + pollingInterval) {
pollKeyStates()
}
}
static func pollKeyStates() {
for (code, wasPressed) in keyStates {
if code.isPressed {
if !wasPressed {
dispatchKeyDown(code)
keyStates[code] = true
}
} else if wasPressed {
dispatchKeyUp(code)
keyStates[code] = false
}
}
scheduleNextPoll(on: pollingQueue)
}
}
struct ContentView: View
{
@StateObject var detector: SpaceDetector
var body: some View
{
Text(
detector.isPressed
? "Spacebar is pressed"
: "Spacebar is not pressed"
).padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(detector: KeyboardManager.spaceDetector)
}
}
@main
struct KeyDetectorApp: App
{
init() {
KeyboardManager.start()
}
var body: some Scene
{
WindowGroup {
ContentView(detector: KeyboardManager.spaceDetector)
}
}
}
@danpaldev
Copy link

This is amazing! Thanks for sharing this!

@chipjarred
Copy link
Author

@danpaldev I'm glad you found it useful

@paulpinter
Copy link

Well done sir!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment