0

I have a UITextView with some text that exceeds its bounds. Thus, vertical scrolling is enabled.

Now I want to find the position of the first visible character. This is what I tried:

let firstCharacterPosition = characterRange(at: contentOffset)?.start

This works in most cases. However, when I scroll up and get close to the beginning of the text, the characterRange(at:) function suddenly returns nil.

In the beginning I thought it was only because of bouncing (when the contentOffset.y value shortly becomes < 0). But that's not the (only) reason.

I tried some other values and was surprised to find that

characterRange(at: .zero)

returns nil as well – just as text positions with a low positive y value.

Why is that?

How can I get a reliable UITextPosition for the first visible character?

Mischa
  • 15,816
  • 8
  • 59
  • 117
  • 1
    I hope this helps you. https://stackoverflow.com/questions/34922331/getting-and-setting-cursor-position-of-uitextfield-and-uitextview-in-swift – Abhishek Jadhav Dec 27 '18 at 06:19
  • No, that answer is about text selection and the cursor position. It doesn't answer this question. – Mischa Dec 27 '18 at 06:23
  • [This seems relevant](https://stackoverflow.com/a/53940761/1032372). – shim Dec 27 '18 at 06:55

1 Answers1

3

Please, try this code (remove textView if you are calling it inside UITextView subclass):

let firstVisibleCharacterIndex = textView.layoutManager.characterIndex(for: textView.contentOffset, in: textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
Yevgeniy Leychenko
  • 1,287
  • 11
  • 25
  • That's returning the correct character _index_ as an integer value and it's probably a step in the right direction, but it's not returning a `UITextPosition` which is what I need for further calculations and it doesn't answer why `characterRange(at: .zero)` is `nil`. – Mischa Dec 27 '18 at 06:58
  • I guess, `characterRange(at: .zero)` is `nil`, because there is no character in (0,0) position. It might be that there is some smallest inset, so that even the first ever character starts at (1,1), for example. If you need `UITextPostion` and cannot modify your code to work with `Int`'s, you might try this `closestPosition(to point: CGPoint) -> UITextPosition?` – Yevgeniy Leychenko Dec 27 '18 at 07:33