I'm slowly learning Objective-C and Cocoa, and the only way I see so far to capture key events in Text Views is to use delegation, but I'm having trouble finding useful documentation and examples on how to implement such a solution. Can anyone point me in the right direction or supply some first-hand help? Thanks in advance!

+4  A: 

Generally, the way you implement it is simply to add the required function to your view's controller, and set its delegate. For example, if you want code to run when the view loads, you just delegate your view to the controller, and implement the awakeFromNib function.

So, to detect a key press in a text view, make sure your controller is the text view's delegate, and then implement this:

- (void)keyUp:(NSEvent *)theEvent

Note that this is an inherited NSResponder method, not a NSTextView method.


So should I have a separate controller (apart from the controller that houses the outlets for my main window) to serve as delegate for the Text View then?

Thanks for your quick answer, by the way.

Brian Warshaw

I've tried doing something with this, and I'm having a bit of trouble. Could you post a short example, with a method implementation? I would greatly appreciate it.

Thanks again.

Brian Warshaw
+1  A: 

It's important to tell us what you're really trying to accomplish — the higher-level goal that you think capturing key events in an NSTextView will address.

For example, when someone asks me how to capture key events in an NSTextField what they really want to know is how to validate input in the field. That's done by setting the field's formatter to an instance of NSFormatter (whether one of the formatters included in Cocoa or a custom one), not by processing keystrokes directly.

So given that example, what are you really trying to accomplish?

Chris Hanson

Hey Chris,

I'd eventually like to write an Actionscript editor/IDE in Cocoa. So my interest in capturing those key events is tied to syntax highlighting. I've never written something with syntax highlighting before, but, based on the behavior of editors I've used, it seems like the code must be evaluated after each keypress, since the highlighting of a keyword typically happens upon the completion of the keyword, and because code hinting in many editors takes place as you type, as well.

Brian Warshaw

I've done some hard digging, and I did find an answer to my own question. I'll get at it below, but thanks to the two fellas who replied. I think that Stack Overflow is a fantastic site already--I hope more Mac developers find their way in once the beta is over--this could be a great resource for other developers looking to transition to the platform.

So, I did, as suggested by Danny, find my answer in delegation. What I didn't understand from Danny's post was that there are a set of delegate-enabled methods in the delegating object, and that the delegate must implement said events. And so for a TextView, I was able to find the method textDidChange, which accomplished what I wanted in an even better way than simply capturing key presses would have done. So if I implement this in my controller:

- (void)textDidChange:(NSNotification *)aNotification;

I can respond to the text being edited. There are, of course, other methods available, and I'm excited to play with them, because I know I'll learn a whole lot as I do. Thanks again, guys.

Brian Warshaw
+3  A: 

Just a tip for syntax highlighting:

Don't highlight the whole text view at once - it's very slow. Also don't highlight the last edited text using -editedRange - it's very slow too if the user pastes a large body of text into the text view.

Instead you need to highlight the visible text which is done like this:

NSRect visibleRect = [[[textView enclosingScrollView] contentView] documentVisibleRect];
NSRange visibleRange = [[textView layoutManager] glyphRangeForBoundingRect:visibleRect inTextContainer:[textView textContainer]];

Then you feed visibleRange to your highlighting code.



Awesome advice, thank you. Very useful stuff.

Brian Warshaw