2

I'm looking to pull the index value (String.Index) from the user cursor position of a UITextView element. I'm using the selectedTextRange method to get the UITextRange value. How can I use that to retrieve the index value?

DaveJ
  • 55
  • 1
  • 6
  • This might help you https://stackoverflow.com/questions/34922331/getting-and-setting-cursor-position-of-uitextfield-and-uitextview-in-swift – rmp Jun 13 '17 at 23:39
  • @rmp That provided a lot of insight! Thank you! – DaveJ Jun 14 '17 at 00:14

1 Answers1

3

You can get the selected range offset from the beginning of your document to the start of the selected range and use that offset to get your string index as follow:

extension UITextView {
    var cursorOffset: Int? {
        guard let range = selectedTextRange else { return nil }
        return offset(from: beginningOfDocument, to: range.start)
    }
    var cursorIndex: String.Index? {
        guard let location = cursorOffset else { return nil }
        return Range(.init(location: location, length: 0), in: text)?.lowerBound
    }
    var cursorDistance: Int? {
        guard let cursorIndex = cursorIndex else { return nil }
        return text.distance(from: text.startIndex, to: cursorIndex)
    }
}

class ViewController: UIViewController, UITextViewDelegate {
    @IBOutlet weak var textView: UITextView!
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
    }
    func textViewDidChangeSelection(_ textView: UITextView) {
        print("Cursor UTF16 Offset:",textView.cursorOffset ?? "")
        print("Cursor Index:", textView.cursorIndex ?? "")
        print("Cursor distance:", textView.cursorDistance ?? "")
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Wonderful! Thank you! – DaveJ Jun 14 '17 at 00:36
  • 2
    I believe this is going to have issues with strings with Emoji and other special characters because the `UITextView` methods used here give the range and offset based on the UTF-16 encoding of the string while the `String index(_:offsetBy:limitedBy:)` method is using actual characters. – rmaddy Nov 10 '17 at 04:25