How to read keyboard state in Swift / MacOS? - swift

I'm writing a game in Swift 3 for Mac OS. I'd like to be able to do "as long as the A key is down, move to the left". In other environments I'm used to a function like KeyIsDown('A'), but I can't find it here.
Does it exist, or do I need to watch every keydown and keyup event and keep track of the state myself? I will be wanting to do this for arrow keys as well as alphabetic keys.

Kudos to BallpointPen, for a clear answer. So I'll just keep a table of key state for every keycode, and switch bits on an off as keyDown and keyUp events come in.

Depending on you use UITextview or UITextfield. So, conforming UITextviewDegelate or UITextfieldDegalate there are some degelate methods that can change keyboard state.

Related

sliding NSSlider blocks NSEvent monitoring for Keys and wise versa, How to catch them congruent

I have an NSView with several NSButton and one NSSlider in it.
I am watching keyCode Events with [NSEvent addLocalMonitorForEventsMatchingMask:...handler:^{}] and change the buttons appearance with .highlighted=YES && NO.
I chose this handler method because I have to act on quite unusual event.keyCode combinations that can not be expressed via [NSButton setKeyEquivalent:(NSString * _Nonnull)] and/or [NSButton setKeyEquivalentModifierMask:(NSEventModifierFlags)].
All works quite well and smooth (all keys can be pressed at once, singular or in any combination) unless NSSlider comes into play for which i use traditional event handling with a predefined Action on a Target.
Symptom: The Slider slides nice until I hit any Key and slides again when lifting Keys.
Or the other way around, when I hit a Key and want to slide, the Slider just does not slide at all.
I hope i just ran into some edge case of NSResponder and NSEvent handling in general and can learn something. My goal is to be able to press any key while dragging freely with the slider at the same time.
So how can i achieve congruent Event Handling/Executing between Keycodes and MouseEvents of KeyEquivalent NSButtons and native modifierFlag changing behaviour of NSSliders in one and the same NSView?
There are two problems that clash.
NSSlider have special behaviour when ⌥ key is down.
And [NSEvent addLocalMonitorForEventsMatchingMask:...handler:^{ }] with a mask set to catch NSEventMaskFlagsChanged will cancel each others functionality out when the flag returns nil into the Responder chain.
The modifierFlags to step NSSlider up and down with its altIncrementValue or other special behaviour in combination with other modifierFlags can not work properly when it never reaches the NSView's action method.
Releasing the key lets the Slider slide again, Keys where useless then.
Pressing a key (specially a flag) sets the NSSlider in stepwise increment mode but its mouse events are dumped as they where not catched from LocalMonitor which was focused on KeyCode events only.
So the solution is to explicit check for event.type == NSEventTypeLeftMouseDown and for sure subclassing NSSlider to change this interferences with flags or to implement a different NSControl imposing as slider.

Handling key events in OS X with Swift and Cocoa

I have a very basic OS X that has a few different elements.
A text field, a table view and a file contents view.
I have a single ViewController.
I'd like to be able to intercept specific key events for each of these elements in the storyboard in my ViewController and change the focus between the different elements.
For example, if the cursor is currently in the file contents view, and I hit ESCAPE, I'd like for the focus to be transferred to the text field.
Or, if the focus is currently on the table view and I hit ENTER, that the cursor/focus is moved to the file contents view.
What's the best way to handle this?
I have tried overriding the keyDown method in the ViewController but with things such as autocomplete getting in the way, I'm not having much luck. I have added a print statement to keyDown to check if the function is receiving events, but it's not always fired.
Update
Except for the specific keys that I want to intercept, I want all other key events to behave as normal. For example, typing in the file contents view, or the text field.
I would highly recommend watching the WWDC talk #145 from 2010, Key Event Handling in Cocoa Applications. It gives an overview of the event delivery mechanism, and several ways of handling events:
Make a menu item or button whose keyEquivalent is the escape key.
Override cancelOperation(_:) or complete(_:), which are the two NSResponder methods which can get invoked by default when the escape key is pressed. (There are other methods for the enter/return key.)
Override sendEvent(_:) in NSApplication or NSWindow to intercept all events and bypass the default behavior.

Is keeping the key pressed equal to pressing the key many times quickly

I'm not sure if this is the right place to ask this question. It's not an application specific question nor it is about any concrete problem. However, to make it more application specific, I'll take the example of Photoshop.
The shortcut to reduce the brush size is [. When I keep it pressed, the brush size reduces quickly with some inertia. I wanted to know how this is implemented. Does it send the keypress event multiple times or does it send the keypress event along with the key down duration, to which the application responds according to the duration?
I suppose this also depends on the OS? I want to know more specifically OSX.
I don't know what's the behavior on OS X, but this article shows some ways how you can find it out by yourself (without reading the developer manuals):
Super User: Mouse button and keypress counter for Mac OS X
On Windows and .NET and "Windows Forms" as the development platform, the behavior would be
MSDN: System.Windows.Forms → KeyPressEventArgs Class
...A KeyPress event occurs when the user presses a key. Two events that are closely related to the KeyPress event are KeyUp and KeyDown. The KeyDown event precedes each KeyPress event when the user presses a key, and a KeyUp event occurs when the user releases a key. When the user holds down a key, duplicate KeyDown and KeyPress events occur each time the character repeats. One KeyUp event is generated upon release...
See also:
MSDN: System.Windows.Input → Keyboard Attached Events
Application code typically handles all three events, while the KeyPress is actually computed from the down/up signals. Because it mimics the signals received from hardware (see http://wiki.osdev.org/Keyboard for more details) which is OS-neutral I'd expect the OS-APIs to be conceptually very similar

Keys pressed - Swift

I am trying to run some code when the user presses the space bar, does anyone know how to do this? Key codes would be helpful. I am programming in Swift an using SpriteKit
Well using google you can search for lists or images of keyboards with the listed keycodes, however I suggest using problem solving for when something like that isn't available. When the keyPress event is called, print the keycode that was pressed. This way, you can press the space bar and it will tell you what the keycode of it was without having to rely on outside sources.

iPhone/iPad keyboard shortcuts?

There's an action in my program which users need to perform very frequently (potentially hundreds of times per session), and I'd like to add a keyboard shortcut for users with a bluetooth keyboard. Is there any way to do this?
Right now, the closest I've come is triggering the action whenever the U+F8FF character is entered (Shift+Alt+k on an iPad/iPhone/Mac, which prints an apple logo character) in a text view. Of course, this would present an issue if the user actually wanted to input an apple symbol.
Are there any better ways to support keyboard shortcuts (hopefully Cmd+something, rather than Shift+Alt+something)? Thanks!
Under Cocoa for Mac OS X, you would gather modifier key information from the NSEvent passed to the keyDown: method in an NSResponder object. CocoaTouch replaces the NSResponder with UIResponder and NSEvent with UIEvent. The UI versions don't have documented keyboard event support. I'm guessing that Apple has extended UIResponder to handle keydown events, but hasn't publicly documented the changes yet. Unfortunately that means we'll just have to wait for that documentation to be able to read the modifier keys.
I think your current solution is a fine solution until Apple gives us a keyboard supporting UIResponder.