32

How can I convert a UITextRange object to an NSRange? I've seen plenty of SO posts about going the other direction but that's the opposite of what I need. I'm using the UITextRange selectedTextRange which is a property of a UITextView. It returns a UITextRange but I need a range.

Peter Lapisu
  • 19,915
  • 16
  • 123
  • 179
Milo
  • 5,041
  • 7
  • 33
  • 59

4 Answers4

58

You need something like this:

- (NSRange) selectedRangeInTextView:(UITextView*)textView
{
    UITextPosition* beginning = textView.beginningOfDocument;

    UITextRange* selectedRange = textView.selectedTextRange;
    UITextPosition* selectionStart = selectedRange.start;
    UITextPosition* selectionEnd = selectedRange.end;

    const NSInteger location = [textView offsetFromPosition:beginning toPosition:selectionStart];
    const NSInteger length = [textView offsetFromPosition:selectionStart toPosition:selectionEnd];

    return NSMakeRange(location, length);
}
Vitaly S.
  • 2,389
  • 26
  • 40
24

Here's a Swift extension based on the answer by Vitaly S.

extension UITextInput {
    var selectedRange: NSRange? {
        guard let range = self.selectedTextRange else { return nil }
        let location = offsetFromPosition(beginningOfDocument, toPosition: range.start)
        let length = offsetFromPosition(range.start, toPosition: range.end)
        return NSRange(location: location, length: length)
    }
}

Swift 4

extension UITextInput {
    var selectedRange: NSRange? {
        guard let range = selectedTextRange else { return nil }
        let location = offset(from: beginningOfDocument, to: range.start)
        let length = offset(from: range.start, to: range.end)
        return NSRange(location: location, length: length)
    }
}
Laszlo
  • 2,803
  • 2
  • 28
  • 33
Daniel Wood
  • 4,487
  • 3
  • 38
  • 36
7

UITextView has a property

@property(nonatomic) NSRange selectedRange;
yasirmturk
  • 1,924
  • 2
  • 22
  • 32
0

Swift 5

extension UITextInput
{
    var selectedRange: NSRange?
    {
        if let selectedRange = self.selectedTextRange
        {
           return NSMakeRange(self.offset(from: self.beginningOfDocument, to: selectedRange.start),
                              self.offset(from: selectedRange.start,      to: selectedRange.end))
        }
        else
        {
            return nil
        }
    }
}
Leslie Godwin
  • 2,601
  • 26
  • 18
  • Your code will be cleaner if you begin with `guard let.. else { return nil }` instead of the way you've written it. – kwiknik Mar 10 '23 at 16:58