Я не проверил это полностью, но я считаю, что следующее должно работать. Необходимые API-интерфейсы документированы в протоколе UITextInput
, который UITextView
принимает.
Сначала необходимо получить UITextPosition
, который соответствует заданной точке в представлении. Затем вы конвертируете это значение в смещение UTF-16. Например, здесь я печатаю диапазон видимого текста (в единицах кода UTF-16), равный textView
каждый раз при прокрутке представления:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let topLeft = CGPoint(x: textView.bounds.minX, y: textView.bounds.minY)
let bottomRight = CGPoint(x: textView.bounds.maxX, y: textView.bounds.maxY)
guard let topLeftTextPosition = textView.closestPosition(to: topLeft),
let bottomRightTextPosition = textView.closestPosition(to: bottomRight)
else {
return
}
let charOffset = textView.offset(from: textView.beginningOfDocument, to: topLeftTextPosition)
let length = textView.offset(from: topLeftTextPosition, to: bottomRightTextPosition)
let visibleRange = NSRange(location: charOffset, length: length)
print("Visible range: \(visibleRange)")
}
В моих тестах UITextView
имел тенденцию подсчитывать строки, которые были едва включены в видимый диапазон (например, только на один пиксель), поэтому сообщаемый видимый диапазон имел тенденцию быть на одну или две строки больше, чем сказал бы пользователь-человек , Возможно, вам придется поэкспериментировать с точным CGPoint
, который вы передаете в closesPosition(to:)
, чтобы получить желаемые результаты.