Cocoa/OS X: Debug Key View Loop
Quick Answer
Get this gist: https://gist.github.com/mittsh/6668638 And use LMWindow instead of NSWindow in IB or anywhere you are creating your window. It will add 2 menu items in your app menu, with keyboard shortcuts: Cmd + O to show an overlay on the first responder and Cmd + P to dump your key view loop in the console.
The Whole Story
Find me one Cocoa developer who never had any problem with the key view loop. Just one. Yet, after Googling and reading a lot of Stack Overflow threads I can't find any good way to debug my key view loop for Paw 2.
The first advise that comes everywhere is to toggle the Full Keyboard Access setting in System Preferences > Keyboard. But in most cases it doesn't help much: NSScrollView, NSClipView, NSMatrix (and many more) are in the key view loop and are mostly invisible because sometimes they pass the first responder status to a child view, plus they don't have a focus ring to make them visible. So I came up with a quick-and-dirty debug solution (see end to get the code):
Yes! It simply highlights the current responder using a child window. You can toggle this highlight using Cmd + O, since it actually adds 2 menu items in the app menu:
And to make deep, console-based debug Cmd + P will help:
Here's who to decode that logs:
When a line is starting with > the responder accepts to be first responder (aka. -acceptsFirstResponder returns YES), it shows - in the other case.
As you guessed, the first column shows the class of that responder
Indents in this column represents the view hierarchy, often the next key view is a descendent view. Note that an indent doesn't necessarily means that a view is a subview of the previous one, it means any descendent (subview of subview...).
The second column shows the identifier you may have set on IB
Again, you guessed it, the memory address (useful to access it from the debugger).
As promised, here's the gist with the full code: https://gist.github.com/mittsh/6668638 Simply create the LMWindow class, and use it for as your window (or make your custom window subclass inherit from this one).









