【问题标题】:Forcing a Cocoa text field to end editing强制 Cocoa 文本字段结束编辑
【发布时间】:2010-02-17 20:29:25
【问题描述】:

我有一个基于视图的 gui,其中包含每个 gui 项的文本字段。当我选择另一个菜单项时,我希望我的文本字段退出编辑模式。我无论如何都找不到在 nsTextField 文档中执行此操作。有任何想法吗?

【问题讨论】:

    标签: cocoa macos nstextfield


    【解决方案1】:

    您需要告诉窗口从控件中删除第一响应者状态:

    [[textField window] makeFirstResponder:nil];
    

    这将结束编辑并从文本字段中移除焦点。

    【讨论】:

    • 在这里的优胜美地工作正常。你是从主线程调用吗? dispatch_async(dispatch_get_main_queue(), ^{[textField.window makeFirstResponder:nil];});
    • 当我有一个专注的NSTextField 并单击NSSlider 时,我遇到了类似的问题......我可以将mouseDown 处理程序添加到NSSlider 以获取焦点,但是我想知道是否有一种好方法可以将其烘焙到 NSTextField 本身,因此在单击任何 NSControl 时它会失去编辑模式 ...
    • 如果直接在窗口控制器的windowDidLoad 方法中的窗口上直接调用,这会起作用吗?我认为它会产生相同的效果,但对我不起作用。还是我把它和别的东西混淆了?
    • windowDidLoad 并不一定意味着窗口是关键。您可以使用NSWindowDelegate 方法windowDidBecomeKey(_ notification: NSNotification),当窗口成为关键窗口时,让第一响应者nil。您必须对此进行管理,以便您实际上可以使窗口接受第一响应者状态:-)
    • [self.view.window makeFirstResponder:nil] 也可以在大多数情况下工作,并且更通用。
    【解决方案2】:

    cocoabuilder.com - Stop edit session with a NSTextField 的以下解决方案适用于我在 OS X 10.9 和 OS X 10.10 上的 Objective-C 以及 10.10 上的 Swift。

    这里是 Objective-C 版本:

    @implementation CustomTextField
    
    - (id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
    
        self.target = self;
        self.action = @selector(action:);
    
        return self;
    }
    
    - (void)action:(NSTextField *)textField {
        // Make something else first responder, something neutral 
        // (or can be a fake invisible element)
        [self.window makeFirstResponder:self.window.contentView];
    
        // Other code
    }
    
    @end
    

    背景:本主题中接受的解决方案在 OS X 10.9 和 10.10 上从未对我有用,因此与其建议的那样调用 [[textField window] makeFirstResponder:nil]; - 我需要使用一些非零 NSResponder 子类调用 makeFirstResponder(这可以是NSWindow 的内容视图或 NSViewController 的视图都适用于我的情况,或者一些假的 NSTextField 视图,对于更复杂的情况,用户不可见)。

    重要细节:-[NSWindow makeFirstResponder] 必须在 NSTextField 的操作选择器中准确调用,如我的示例所示。 NSTextField 方法管道中没有其他地方对我有用(textDidEndEditing:、textShouldEndEditing: 或 control:textShouldEndEditing:)

    【讨论】:

    • 虽然很奇怪,但这也是唯一对我有用的解决方案。
    • 在优胜美地,这确实有效,而接受的答案却没有
    • 如果您在 viewWillLayout 中调用了上述答案中的方法,那么您将在一行中完成所有操作而无需创建任何子类。
    • 这个解决方案对我有用,但只有在按下 Enter 时,按下 TAB 按钮时它仍然不起作用。
    【解决方案3】:

    我知道这是一个老问题,但如果有人想知道 swift 3,它只对我有用

    DispatchQueue.main.async {
        self.window?.makeFirstResponder()
    }
    

    Swift 4.2 更新,nil 使窗口成为它的第一响应者。否则抛出错误。

    DispatchQueue.main.async {
        self.window?.makeFirstResponder(nil)
    }
    

    【讨论】:

    • 我不知道如何挽救我的生命,但这确实有帮助。 :) 我还想指出,就我而言,不是 makeFirstResponder 而是 resignFirstResponder 必须包装在调度队列中。
    【解决方案4】:

    此命令应在 viewWillLayout 中使用,如果需要在 viewWillAppear 和 .就这样。没有子类和并行线程。

    [textField.window makeFirstResponder:nil];
    

    这适用于主窗口。但这不适用于模态窗口。

    对于模态窗口,使用 viewDidAppear 或 dispatch_async:

    dispatch_async(dispatch_get_main_queue(), ^{
            [textField.window makeFirstResponder:nil];
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多