I'm currently working on a Preference Pane. I would like a custom NSView subclass to have First Responder status upon launch of my Preference Pane. I set my view to be first responder as such (within my NSPreferencePane subclass):
- (void)didSelect {
NSLog(@"Before: %@", self.mainView.window.firstResponder);
[self.keyboardView.window makeFirstResponder:self.keyboardView];
NSLog(@"After: %@", self.mainView.window.firstResponder);
}
I periodically check the current First Responder thereafter, and it seems that shortly after didSelect finishes, the First Responder is changed to the mainView of my NSPreferencePane. Nothing in my program is causing this change. Here is the output:
Before: <NSTextView: 0x60000013dce0>
//presumably the System Preferences search field.
After: <AMKeyboardView: 0x608000321a40>
//successfully set to the desired AMKeyboardView.
<NSView: 0x61000013ea00>
//<--- magic change to mainView, for seemingly no reason.
In Interface Builder, my window has an outlet called initialFirstResponder. I can't set this outlet to anything, because my view is added programatically, and isn't accessible by Interface Builder. I suspect the lack of connection is leading to a default behaviour which sets the first responder to the mainView.
What can I do to troubleshoot this?
After looking at the source code the Secrets Preference Pane, I found the method by which they set their own search box as the first responder when the preference pane is opened. I applied this method to my own pref pane by adding to my didSelect
method:
[self.mainView.window performSelector:@selector(makeFirstResponder:)
withObject:self.keyboardView
afterDelay:0.0];
...and it works! However, I have no idea why it works. I assume the 0.0 delay isn't actually truly instant, which makes this performSelector run after the mysterious first responder change has occurred.
I suppose this answers my question, but leads to a new one: why does this work?