End editing in an NSTextField

December 17, 2006

A few weeks ago I read a blog post by Daniel Jalkut on how to commit editing in an NSTextField. The basic idea is when you want to end editing (or just validate the current value), you call [window makeFirstResponder:nil]. This validates the text field’s value, commits the changes, and resigns the text field as the first responder.

I’ve known this for a while, but what I didn’t know was how to restore the first responder afterwards. Although you can get the current first responder by calling [window firstResponder], trying to make this object first responder afterwards does not seem to do anything. What Daniel realized was that this object is not the NSTextField we’re dealing with, but the window’s field editor. You can get a reference to the actual text field you want through the field editor’s delegate.

I rewrote this slightly for my own use, and packaged it up into an NSWindow category. See Daniel’s post for a code snippet with a few more comments.


@implementation NSWindow (NSWindowAdditions)

- (bool)endEditing;
{
	bool success;
	id responder = [self firstResponder];

	// If we're dealing with the field editor, the real first responder is
	// its delegate.

	if ( (responder != nil) && [responder isKindOfClass:[NSTextView class]] && [(NSTextView*)responder isFieldEditor] )
		responder = ( [[responder delegate] isKindOfClass:[NSResponder class]] ) ? [responder delegate] : nil;

	success = [self makeFirstResponder:nil];

	// Return first responder status.

	if ( success && responder != nil )
		[self makeFirstResponder:responder];

	return success;
}

- (void)forceEndEditing;
{
	[self endEditingFor:nil];
}

@end

Again, thanks to Daniel Jalkut for this.

Marc Charbonneau is a mobile software engineer in Portland, OR. Want to reply to this article? Get in touch on Twitter @mbcharbonneau.