开发者

Forcing a Cocoa text field to end editing

I have a view based gui that contains a text field for each gui item. When I select another menu item I want my text fields to exit out of editing mode. I could not find anyway to do this in the nsTe开发者_JAVA技巧xtField docs. Any ideas?


You need to tell the window to remove first responder status from the control:

[[textField window] makeFirstResponder:nil];

This will end editing and remove focus from the text field.


The following solution from cocoabuilder.com - Stop edit session with a NSTextField works for me both on OS X 10.9 and OS X 10.10 for Objective-C and on 10.10 for Swift.

Here is Objective-C version:

@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

Background: accepted solution in this topic never worked for me on OS X 10.9 and 10.10 so instead of calling [[textField window] makeFirstResponder:nil]; as it suggests - I needed to call makeFirstResponder with some non-nil NSResponder subclass (this can be either NSWindow's content view or NSViewController's view that both work in my case or some fake NSTextField view which is not visible to user for more complex cases).

Important detail: -[NSWindow makeFirstResponder] must be invoked exactly within NSTextField's action selector like my example demonstrates. No other place in NSTextField method pipeline did work for me (textDidEndEditing:, textShouldEndEditing: or control:textShouldEndEditing:)


i know this is an old question, but in case anyone is wondering about swift 3, it only worked for me with

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

Swift 4.2 udpate, nil makes the window its first responder. Otherwise throws error.

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


This command should be used in viewWillLayout and if need in viewWillAppear and . And that's all. No subclasses and parallel threads.

[textField.window makeFirstResponder:nil];

This works well with the main window. But this does not work well with modal windows.

For modal windows use viewDidAppear or dispatch_async:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜