在 Cocoa Mac OSX 中设置 FirstResponder 的问题
Posted
技术标签:
【中文标题】在 Cocoa Mac OSX 中设置 FirstResponder 的问题【英文标题】:Problems setting FirstResponder in Cocoa Mac OSX 【发布时间】:2011-08-31 21:13:00 【问题描述】:我正在开发一个小应用程序,只是为了学习可可,而且我很难将 FirstResponder 设置为一些 NSTextFields。
当视图打开时,我希望选择第一个 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] delegate]; [appDelegate.window makeFirstResponder:self.invoiceCredit]; 而不是成为FirstResponder。但是还是不行。
【问题讨论】:
【参考方案1】:你让这件事变得比需要的困难得多。
在 Interface Builder 中,将窗口的 initialFirstResponder
出口设置为指向您的文本字段。
就是这样。
如果您绝对必须以编程方式进行,请使用:
[window setInitialFirstResponder:yourTextField];
请记住,如果您正在与 Cocoa 争吵做一些看起来应该很简单的事情,那么您可能做错了。
【讨论】:
第一次打开窗口时没有加载文本字段。根据用户在窗口中单击的按钮,将加载五个不同的视图。所以这就是为什么我必须稍后将焦点设置到适当的文本字段。 不适用于 SplitViewControllers 之类的东西。在 viewDidAppear 中以编程方式设置它【参考方案2】:重写viewDidAppear,并在该方法中调用NSTextField的becomeFirstResponder方法。
请注意,在我自己的工作中,无论是使用 NSTextField 的 becomeFirstResponder 方法还是使用 NSWindow 的 makeFirstResponder 方法,viewWillAppear 都被证明太早了。
【讨论】:
【参考方案3】:问题是 self.view.window 在第一个视图控制器的 viewDidLoad 方法中为空,直到 applicationDidFinishLaunching 退出。因此,becomeFirstResponder 在 viewDidLoad 中不起作用。尝试延迟第一响应者的设置,如下所示:
[_yourTextField performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.1];
【讨论】:
【参考方案4】:您不应该尝试在 viewDidLoad 方法中设置第一响应者,因为此时 window 仍然为零。改用 viewWillAppear:
- (void)viewWillAppear
[super viewWillAppear];
if (!_started)
_started = YES;
[self.view.window makeFirstResponder:_yourView];
Apple 也曾经说过,你永远不应该直接调用 becomeFirstResponder。请改用 [yourWindow makeFirstResponder:yourView];。
【讨论】:
你说得对。。这个话题应该早就关闭了,这个问题在6年前发布时是相关的。 API 现在不同了,无论如何这都是错误的方法。 ;) 我刚刚添加了这个答案来帮助其他人解决 Cocoa 问题。【参考方案5】:只需阅读文档:
成为第一响应者
通知接收者它即将成为 NSWindow 中的第一响应者。
[...]
使用 NSWindow makeFirstResponder: 方法,而不是这个方法,使 第一响应者的对象。切勿直接调用此方法。
【讨论】:
谢谢,我尝试使用:FakturaAppDelegate *appDelegate = (FakturaAppDelegate *)[[NSApplication sharedApplication] delegate]; [appDelegate.window makeFirstResponder:self.invoiceCredit];而不是成为FirstResponder,它仍然不起作用。 这拯救了我的一天,+1以上是关于在 Cocoa Mac OSX 中设置 FirstResponder 的问题的主要内容,如果未能解决你的问题,请参考以下文章
sh 使用HomeBrew在Mac OSX中设置Golang。在zshell,fish或bash中设置`GOPATH`和`GOROOT`变量。
sh 使用HomeBrew在Mac OSX中设置Golang 1.5。在zshell或bash中设置`GOPATH`和`GOROOT`变量。
sh 使用HomeBrew在Mac OSX中设置Golang 1.5。在zshell或bash中设置`GOPATH`和`GOROOT`变量。
Objective C - 创建 PDF (Mac OSX / Cocoa)