3
votes

So I have a UITextView that the user can edit, but there may also be some text inserted programmatically into the textView as well, and it could be inserted at any arbitrary range in the textView. Currently, this also moves the caret position from where the user was currently working, which is undesirable. So anytime I do this:

self.textView.text = //some text inserted

It moves the caret position. So what would be the best way to prevent the caret position from moving, or make it totally ignorant and independent of programmatic changes and only move in response to user changes?

3

3 Answers

1
votes

The best answer would be to set the text that is inserted like you have, but then after, set the caret position using the following method:

textView.selectedRange = NSMakeRange(0,0)

The first number is the spot in the text view you would like to put the caret. If you would like to keep it at the beginning regardless of whatever text is added, this is how you would do it. You would, however, want to include a conditional to keep this only around the non-typed text being added. When the user is typing, you want the caret to move.

0
votes

Before you programatically insert your text, you can get the current insertion point via UITextView's "selectedRange" property.

Once you're done inserting the new text, you can reset the text view's selected range to what it was prior to insertion... or, if the insertion point was before the new block of text inserted, you'll need to recalculate the position of the previous caret location taking into account the length of the inserted text.

0
votes

I think you're supposed to use the UITextView's textStorage property.

For example:

let string = "some text"
let range = NSRange(location: 4, length: 0) // arbitrary range
textView.textStorage.replaceCharacters(in: range, with: string)

Doing it this way doesn't cause the cursor to move.

Note: If you initialize a UITextView the typical way—for example, in code it's just UITextView(frame: .zero, textContainer: nil)—then textStorage gets set to an instance of NSConcreteTextStorage, which is a subclass of NSTextStorage, which is a subclass of NSMutableAttributedString.