2013-04-23

I recently had to debug a complex Responder Chain-related bug:

Did you know that when you send a nil-targeted action message, but there’s no first responder, the chain is started from the sender of the message? It seems to make sense, but I can’t find mention of it in the documentation.1

Anyway, I ended up writing a few utility methods to help me track this bug. Here they are:

@interface UIView (NBResponderChainUtilities)
- (UIView*) nb_firstResponder; // Recurse into subviews to find one that responds YES to -isFirstResponder
@end
 
@interface UIApplication (NBResponderChainUtilities)
- (UIView*) nb_firstResponder; // in the -keyWindow
@end
 
@interface UIResponder (NBResponderChainUtilities)
- (NSArray*) nb_responderChain; // List the -nextResponder starting at the receiver
@end

UIView * NBFirstResponder(void); // in the app key window
NSArray * NBResponderChain(void);  // Starting at the first responder

Armed with this, you can simply po the responder chain in the debugger:

(lldb) po NBResponderChain()
$13 = 0x213dda70 <__NSArrayI 0x213dda70>(
<UIActionSheet: 0x11915160; frame = (0 231; 320 337); opaque = NO; ...
<UIView: 0x222c73b0; frame = (0 0; 320 568); opaque = NO; layer ...
<UIView: 0x2229d340; frame = (0 0; 320 568); opaque = NO; layer ...
<UIView: 0x11913dc0; frame = (0 0; 320 568); clipsToBounds = YES; ...
<_UIAlertOverlayWindow: 0x2226d4e0; frame = (0 0; 320 568); layer ...
<UIApplication: 0xaa66b30>,
<BicycletteApplicationDelegate: 0xab78c60>
)

It is available as a gist.

Enjoy and share; comments are welcome, via nico@bou.io or on twitter.

  1. If I lost you at “nil-targeted”, go read the docs. The Responder Chain is one of the most powerful features of Cocoa(Touch), but it’s largely being ignored on iOS.