6

I am using the following code to deselect an NSTextView, as suggested here. Unfortunately, nothing at all happens. I have tried what I know to debug it, but everything seems to be working correctly, but it doesn't affect the NSTextView.

The code:

// Sets the scrolling bounds and behavior. This might be useful, but I don't know
[[textView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[[textView textContainer] setWidthTracksTextView:FALSE];

// The code for deselecting, beginning by making sure it is actually selected (for testing only, as strange as it is)

[textView setSelectable:TRUE];
[textView setDelegate:self];
[_window makeFirstResponder:textView];

NSText *fieldEditor = [_window fieldEditor:TRUE forObject:textView];
[fieldEditor setSelectedRange:NSMakeRange([[fieldEditor string] length],0)];
[fieldEditor setNeedsDisplay:YES];

Any ideas about why this doesn't work? I am sure my outlets are set properly because I can manipulate other things, such as it's string value.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Justin
  • 2,122
  • 3
  • 27
  • 47
  • 2
    That cocoa-dev (I assume) thread is about NSText*Field*, not NSText*View*. The two are very different: NSTextField is a kind of control and, as such, is dependent upon the field editor, while NSTextView is not a control and does not use the field editor. – Peter Hosey Nov 21 '11 at 01:25
  • I did not even notice. Thanks a lot. – Justin Nov 21 '11 at 02:47

6 Answers6

8

I'm not sure NSTextViews use the field editor, have you tried calling the method on the text view directly?

[textView setSelectedRange:NSMakeRange(textView.string.length, 0)];

The range location can be adjusted to move the cursor to the start or end, for example. You may also want to check to make sure something is actually selected before calling this method.

EDIT:

From your comment it sounds like you just want it to resign first responder. You can do that manually by calling [textView.window makeFirstResponder:nil];

Francis McGrew
  • 7,264
  • 1
  • 33
  • 30
  • 1
    Text views don't use the field editor. Only text fields (and possibly similar controls, such as combo boxes) do. – Peter Hosey Nov 21 '11 at 01:24
  • That's what I thought. Unless Justin is using a NSTextField or something the above code should just work. – Francis McGrew Nov 21 '11 at 01:33
  • Not doing anything. Is there another way to deselect it? By the way, it is an NSTextView, so you were right. – Justin Nov 21 '11 at 02:49
  • 2
    @Justin: There is no such thing as deselection; an insertion point is a selection of empty length. Francis's answer will deselect whatever is selected and establish an empty selection (insertion point) at the end of the text. Assuming that `textView` is pointing to an NSTextView (as opposed to `nil`), and that the selection you seek to deselect is not actually being set after this code runs, Francis's suggestion should work. – Peter Hosey Nov 21 '11 at 02:59
  • I want to make it so when you press keys, you are not typing into the NSTextView. – Justin Nov 21 '11 at 17:35
6

This almost worked for me;

[textView.window makeFirstResponder:nil];

However, I had trouble setting the first responder to nil. If I set it to any other view it seems to do as you want.

[textView.window makeFirstResponder:[textView superview]];

Tested in 10.7 Lion.

user1330493
  • 61
  • 1
  • 2
2

I've using this approach and it works perfectly:

[textView setSelectedRange:NSMakeRange(0, 0)];
aumanets
  • 3,703
  • 8
  • 39
  • 59
2

As suggested earlier setSelectedRange: will do the trick BUT!

If your goal is to completely remove the selection and the cursor too, f.e. if you subclass an NSTextView to support similar behavior like NSTextEdit has in case of firstResponder status change you should write:

- (BOOL)resignFirstResponder
{
    // Invalid range location will remove cursor too
    [self setSelectedRange:NSMakeRange(NSUIntegerMax, 0)];  
    return YES;
}
//------------------------------------------------------------------------------

- (BOOL)becomeFirstResponder
{
    [self setSelectedRange:NSMakeRange(0, self.string.length)];
    return YES;
}
//------------------------------------------------------------------------------
Hofi
  • 945
  • 1
  • 6
  • 18
-2
[textView setDelegate:self];

I have a feeling that one of your delegate methods is preventing things from happening. See the documentation under "Managing the selection".

Ben
  • 1,292
  • 9
  • 17
-2

As a temporary solution, just until somebody comes up with a better idea, setHidden: can be used. I am sure this is not as efficient as is recommended, but it deselects the NSTextView.

Simply toggle it twice, like so:

[textView setHidden:TRUE];
[textView setHidden:FALSE];
Justin
  • 2,122
  • 3
  • 27
  • 47