Im working on a tiny app just to learn cocoa, and Im having a hard time with setting FirstResponder to some NSTextFields.
When the view opens, I want the first NSTextField, clientNumber, to be selected, so I trigger [clientNumber becomeFirstResponder] at the end of my loadView method, but it does not select the text field. But when I click the button that fires the (IBAction)addToArray method, it selects the right text field. Further do I have another text field, it should contain integers only, so I have a crude verification for it. When the content is not a int, I get a beep, just like it should, but it does not select the text field.
Here is my code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
NSLog(@"initWithNibName");
}
return self;
}
- (void)viewWillLoad {
NSLog(@"viewWillLoad");
}
- (void)viewDidLoad {
NSLog(@"viewDidLoad");
[self initNewInvoice];
}
- (void)loadView {
NSLog(@"loadView");
[self viewWillLoad];
[super loadView];
[self viewDidLoad];
FakturaAppDelegate *appDelegate = (FakturaAppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate.window makeFirstResponder:self.clientNumber];
}
- (void)awakeFromNib
{
NSLog(@"awakeFromNib");
}
- (IBAction)saveInvoice:(id)sender
{
FakturaAppDelegate *appDelegate = (FakturaAppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate.window makeFirstResponder:self.invoiceCredit];
}
- (IBAction)addToArray:(id)sender
{
[clientNumber setStringValue: @"Toodeloo"];
FakturaAppDelegate *appDelegate = (FakturaAppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate.window makeFirstResponder:self.clientNumber];
}
- (IBAction)updateCreditDays:(id)sender
{
if(invoiceCredit.intValue){
[self updateCredit];
}else{
NSBeep();
FakturaAppDelegate *appDelegate = (FakturaAppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate.window makeFirstResponder:self.invoiceCredit];
}
}
I really hope someone can help me out here.
EDIT:
I got it all wrong, thanks for the pointers, but when I fix the code, using this: FakturaAppDelegate *appDelegate = (FakturaAppDelegate *)[[NSApplication sharedApplication] delegate]; [appDelegate.window makeFirstResponder:self.invoiceCredit]; instead of becomeFirstResponder. But it still doesnt work.
You are making this much harder than it needs to be.
In Interface Builder, set the
initialFirstResponder
outlet of your window to point to your text field.That's it.
If you absolutely must do it programmatically, use:
Remember, if you're fighting with Cocoa to do something that seems like it should be simple, then you're probably doing it wrong.
Override viewDidAppear, and within said method, call the NSTextField's becomeFirstResponder method.
Note that in my own work, viewWillAppear has proven to be too early for said call, whether using the NSTextField's becomeFirstResponder method or the NSWindow's makeFirstResponder method.
You should never try to set first responder in viewDidLoad method because window is still nil at that point. Use viewWillAppear instead:
Apple also once said that you should never call becomeFirstResponder directly. Use [yourWindow makeFirstResponder:yourView]; instead.
The trouble is that self.view.window is null in the first view controller's viewDidLoad method until after applicationDidFinishLaunching exits. So, becomeFirstResponder doesn't work in viewDidLoad. Try delaying the setting of the first responder, like so:
Just read the documentation: