【问题标题】:Problems setting FirstResponder in Cocoa Mac OSX在 Cocoa Mac OSX 中设置 FirstResponder 的问题
【发布时间】: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。但是还是不行。

【问题讨论】:

    标签: objective-c cocoa nstextfield first-responder becomefirstresponder


    【解决方案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 在 vi​​ewDidLoad 中不起作用。尝试延迟第一响应者的设置,如下所示:

      [_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
        猜你喜欢
        • 2014-09-14
        • 1970-01-01
        • 1970-01-01
        • 2011-01-26
        • 1970-01-01
        • 2012-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多