0
votes

I'm overriding becomeFirstResponder to know when my NSTextField is focused. Once focused, I'm trying to move the cursor to the end. The following snippet does not work:

@interface MyTextField : NSTextField
@end

@implementation MyTextField

- (BOOL)becomeFirstResponder
{
  if ([super becomeFirstResponder]) {
    self.currentEditor.selectedRange = NSMakeRange(self.stringValue.length, 0);
    return YES;
  }
  return NO;
}

@end

By overriding textView:didChangeSelection:, I found that the selection is made, but it's then overwritten by some internal code that runs in response to the NSEventTypeLeftMouseDown event.

The logs look like this:

location=0, length=25

location=25, length=0 // The desired selection.

location=0, length=0

location=5, length=0 // Where the user clicked.
2
A little hacky, but you could queue the self.currentEditor.selectedRang... code to run on the next event loop. - James Bucanek

2 Answers

0
votes

Override the mouseDown: method in your NSTextField subclass.

Then, set selectedRange after calling super.

- (void)mouseDown:(NSEvent *)event
{
  [super mouseDown:event];
  self.currentEditor.selectedRange = NSMakeRange(self.stringValue.length, 0);
}

NSTextField only has its mouseDown: method called when its "field editor" is not yet focused, so the user can still change the selection after the NSTextField gains focus.

This isn't a perfect solution, because the user may have focused the NSTextField indirectly (eg: with the Tab key). You can always set selectedRange in both mouseDown: and becomeFirstResponder though.

0
votes

Use performSelector:withObject:afterDelay: from inside becomeFirstResponder to ensure the selectedRange is set after the NSEventTypeLeftMouseDown event is handled.

- (BOOL)becomeFirstResponder
{
  if ([super becomeFirstResponder]) {
    [self performSelector:@selector(textFieldDidFocus) withObject:nil afterDelay:0.0];
    return YES;
  }
  return NO;
}

- (void)textFieldDidFocus
{
  self.currentEditor.selectedRange = NSMakeRange(self.stringValue.length, 0);
}