Handling key events in OS X with Swift and Cocoa - swift

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.

Related

How to read keyboard state in Swift / MacOS?

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.

Inner Workings of Unity3d's GUI.Button

I'm still pretty new to scripting in Unity3D, and I'm following along with a tutorial that uses GUI.Button() to draw a button on the screen.
I am intrigued by how this function works. Looking through the documentation, the proper use of GUI.Button is to invoke the function in an if statement and put the code to be called when the button is pushed within the if statement's block.
What I want to know is, how does Unity3D "magically" delay the code in the if statement until after the button is clicked? If it was being passed in as a callback function or something, then I could understand what was going on. Perhaps Unity is using continuations under the hood to delay the execution of the code, but then I feel like it would cause code after the if statement to be executed multiple times. I just like to understand how my code is working, and this particular function continues to remain "magical" to me.
I don't know if it's the right term, but I usually refer to such system as immediate mode GUI.
how does Unity3D "magically" delay the code in the if statement until
after the button is clicked?
GUI.Button simply returns true if a click event happened inside the button bounds during last frame. Basically calling that function you are polling: every frame for every button asking the engine if an event which regards that button (screen area) is happened.
If it was being passed in as a callback function or something, then I
could understand what was going on
You are probably used to an MVC like pattern, where you pass a controller delegate that's called when an UI event is raised from the view. This is something really different.
Perhaps Unity is using continuations under the hood to delay the
execution of the code, but then I feel like it would cause code after
the if statement to be executed multiple times.
No. The function simply returns immediately and return true only if an event happened. If returns false the code after the if won't be executed at all.
Side notes:
That kind of system is hard to maintain, especially for complex structured GUI.
It has really serious performance implications (memory allocation, 1 drawcall for UI element)
Unless you are writing an editor extension or custom inspector code, I'd stay away from it. If you want to build a menu implement your own system or use an external plugin (there are several good ones NGUI, EZGUI,..).
Unity has already announced a new integrated UI System, it should be released soon.
Good question. The unity3d gui goes through several event phases, or in the documentation
Events correspond to user input (key presses, mouse actions), or are UnityGUI layout or rendering events.
For each event OnGUI is called in the scripts; so OnGUI is potentially called multiple times per frame. Event.current corresponds to "current" event inside OnGUI call."
In OnGUI you can find out which event is currently happening with >Event.current
The following events are processed link:
Types of UnityGUI input and processing events.
-MouseDown
-MouseUp,mouse button was released
-MouseMove,Mouse was moved (editor views only)
-MouseDrag,Mouse was dragged
-KeyDown, A keyboard key was pressed
-KeyUp A keyboard key was released.
-ScrollWheel The scroll wheel was moved.
-Repaint A repaint event. One is sent every frame.
-Layout A layout event.
-DragUpdated Editor only: drag & drop operation updated.
-DragPerform Editor only: drag & drop operation performed.
-DragExited Editor only: drag & drop operation exited.
-Ignore Event should be ignored.
-Used Already processed event.
-ValidateCommand Validates a special command (e.g. copy & paste).
-ExecuteCommand Execute a special command (eg. copy & paste).
-ContextClick User has right-clicked (or control-clicked on the mac).
Unity GUI has much improved lately and is quite usefull if you want to handle things programmatically. If you want to handle things visually, i recommend looking at the plugins heisenbug refers to.
If you decide to use unity gui, i recommend using only one object with ongui, and let this object handle all your gui.

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.

RichEdit control: Determine when text is changed?

I'm trying to count the number of times that text is changed in a given RichEdit control. I considered using events like key down, but that gets messy when you consider keys that don't change the text (like arrows, page up, etc). And how do you make sure you get all of those keys?
It seems it would be simpler to register a callback for a onTextChanged event, if one exists. Is there any way to do something like that?
Well you need to listen to the EN_CHANGE message if your using C++. Note that you also have to call SetEventMask with ENM_CHANGE to receive these notifications unlike a normal edit control will sends these messages by default.

iPhone numberpad with decimal point

I am writing an iPhone application which requires the user to enter several values that may contain a decimal point (currency values, percentages etc.). The number of decimal places in the values varies. The problem is that the number pad does not contain a key for entering a decimal point.
When I lock my phone, the number pad that comes up to enter a passcode has a custom button to make an emergency call (as seen in the following screenshot):
Numberpad with custom button http://img25.imageshack.us/img25/6426/photoejg.jpg
Does anyone know how to create a number pad with a decimal point button or a custom button (like the emergency call button above)?
Thanks.
There's no Apple-approved way to edit the existing keyboard. If you want them to allow it, file a feature request.
That said, it just so happens that in most applications the keyboard (instance of UIKeyboard) is a separate UIWindow, and you can iterate over the windows in the application and start adding custom subviews that respond to the appropriate touch actions. Find it by iterating over [[UIApplication sharedApplication] windows] and checking to see if the description contains the string UIKeyboard. For more info on this method and some sample code, see this answer.
Another approach is to create your own custom view and build a keyboard from scratch. Be careful if you do this, though, as it requires a lot of manual work, not only in creating the keyboard and getting the touch behavior to match Apple's, but also in any control you add that would bring up the regular keyboard - you'll need to redirect things like becomeFirstResponder to show your own keyboard, rather than Apple's.
Edit: As ZaBlanc pointed out, newer versions of iOS have a way to do this with the inputView and inputAccessoryView properties. See the UIResponder class reference for details.
set UIKeyboardType to UIKeyboardTypeDecimalPad
Available in iOS 4.1 and later.
Create a UIViewController that contains a UIView with a bunch of buttons. Now your keyboard can have whatever you want on it.