Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a robust way to detect first responder changes in subviews?

I'm building a custom view that contains several other subviews (NSTextField, WebView,...). I'd like to have my custom view draw a different border when one of the subviews is the first responder, and act as a single item that can be acted upon with menu items and keyboard shortcuts. It looks something like this:

+-------------+
| NSTextField |
+-------------+
| WebView     |
+-------------+

So far, I've had success subclassing NSTextField and others to notify a delegate when - (BOOL)becomeFirstResponder and - (BOOL)resignFirstResponder are called. This approach doesn't work with WebView though, as it itself contains many subviews--I can't subclass them all!

Is there a better way to detect when subviews change their first responder status? Or a better way to create a custom view?

like image 496
Joseph North Avatar asked Aug 08 '13 09:08

Joseph North


1 Answers

A different approach would be to override the -makeFirstResponder: method on NSWindow to send out a notification.

- (BOOL)makeFirstResponder:(NSResponder *)responder {
  id previous = self.firstResponder ?: [NSNull null];
  id next = responder ?: [NSNull null];

  NSDictionary *userInfo = @{
    BrFirstResponderPreviousKey: previous,
    BrFirstResponderNextKey: next,
  };

  [[NSNotificationCenter defaultCenter] postNotificationName:BrFirstResponderWillChangeNotification object:self userInfo:userInfo];

  return [super makeFirstResponder:responder];
}

You can then listen for the notification in your custom view or a view controller and check if the previous or next responders are subviews using -isDescendantOf: and set needsDisplay as needed.

This is not an ideal solution though, because the custom view is no longer self-contained. It works for now, but hopefully a better approach will be shared.

like image 59
Joseph North Avatar answered Sep 20 '22 11:09

Joseph North