在Cocoa Mac OSX中设置FirstResponder的问题

问题描述:

为了学习可可,我正在一个小应用程序中工作,并且Im很难将FirstResponder设置为某些NSTextFields。在Cocoa Mac OSX中设置FirstResponder的问题

当视图打开时,我想要选择第一个NSTextField,clientNumber,所以我在我的loadView方法结束时触发[clientNumber becomeFirstResponder],但它不选择文本字段。 但是当我点击触发(IBAction)addToArray方法的按钮时,它会选择正确的文本字段。此外,我还有另一个文本字段,它应该只包含整数,所以我有一个粗略的验证。当内容不是int时,我会听到一声嘟嘟声,但它不会选择文本字段。

这里是我的代码:

- (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]; 
    } 
} 

我真的希望有人能帮助我在这里。

编辑:

我得到了它的指针都错了,谢谢你,但是当我修复代码,使用此: FakturaAppDelegate *的appDelegate =(FakturaAppDelegate *)[的NSApplication sharedApplication]代表]; [appDelegate.window makeFirstResponder:self.invoiceCredit]; 而不是成为FirstResponder。但它仍然无法正常工作。

你正在做这比它需要更难。

在Interface Builder中,将窗口的initialFirstResponder出口指向您的文本字段。

就是这样。

如果你绝对必须以编程方式做到这一点,使用:

[window setInitialFirstResponder:yourTextField]; 

请记住,如果你与可可的战斗做一些事情,似乎应该是简单的,那么你很可能就错了。

+0

当窗口首先打开时,文本字段未加载。根据用户在窗口中单击哪个按钮,会加载五个不同的视图。所以这就是为什么我必须将焦点放在适当的文本字段。 –

只是阅读文档:

becomeFirstResponder

通知接收器,它是即将成为 第一个响应者在其NSWindow。

[...]

使用NSWindow makeFirstResponder:方法,没有这种方法,使 对象的第一个响应者。永远不要直接调用这个方法。

+0

谢谢,我试过使用:FakturaAppDelegate * appDelegate =(FakturaAppDelegate *)[[NSApplication sharedApplication] delegate]; [appDelegate.window makeFirstResponder:self.invoiceCredit];而不是成为FirstResponder,它仍然不起作用。 –

问题在于,在applicationDidFinishLaunching退出之后,self.view.window在第一个视图控制器的viewDidLoad方法中为null。因此,becomeFirstResponder在viewDidLoad中不起作用。尝试延迟所述第一应答器的设定,如下所示:

[_yourTextField performSelector:@selector(becomeFirstResponder) withObject:无afterDelay:0。1];

你不应该尝试设置第一个响应者在viewDidLoad中方法,因为窗口是在这一点上仍然为零。用viewWillAppear代替:

- (void)viewWillAppear 
{ 
    [super viewWillAppear]; 
    if (!_started) { 
     _started = YES; 
     [self.view.window makeFirstResponder:_yourView]; 
    } 
} 

苹果也曾经说过你不应该直接调用becomeFirstResponder。使用[yourWindow makeFirstResponder:yourView];代替

+0

你说得对。这个话题应该很久以前就已经关闭了,这个问题在6年前发布时是相关的。 API现在不同了,反正这也是错误的方法。 ;) –

+0

我刚刚添加了这个答案,以帮助与可可问题的其他人。 – Borzh

重写viewDidAppear,并在该方法内调用NSTextField的becomeFirstResponder方法。

请注意,在我自己的工作中,无论使用NSTextField的becomeFirstResponder方法还是NSWindow的makeFirstResponder方法,viewWillAppear已被证明对于所述调用来说为时尚早。