Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 nsTextField docs. Any ideas?

like image 596
Mike2012 Avatar asked Feb 17 '10 20:02

Mike2012


3 Answers

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.

like image 64
Rob Keniger Avatar answered Oct 15 '22 14:10

Rob Keniger


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:)

like image 43
Stanislav Pankevich Avatar answered Oct 15 '22 15:10

Stanislav Pankevich


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)
}
like image 8
joe Avatar answered Oct 15 '22 14:10

joe