Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITextView firstRectForRange returns wrong frame

Edit

The simple solution is to move any frame calculations from viewDidLoad to viewDidAppear:


I'm having a difficult time getting the following code to work properly

The code returns the first frame for a given NSRange in a UITextView.

It works if there are no line breaks, but I get some strange behavior when I add line breaks in the UITextView.

@implementation UITextView (TextFrame)

- (CGRect)frameOfTextRange:(NSRange)range {
    UITextPosition *beginning = self.beginningOfDocument;
    UITextPosition *start = [self positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [self positionFromPosition:start offset:range.length];
    UITextRange *textRange = [self textRangeFromPosition:start toPosition:end];
    CGRect rect = [self firstRectForRange:textRange];

    return [self convertRect:rect fromView:self.textInputView];
}

@end

@implementation DetailViewController

- (void)viewDidLoad 
{
    [super viewDidLoad];
   if (self.searchString) {
        CGRect rect = [self.textView frameOfTextRange:[self.textView.text rangeOfString:self.searchString]];
        ...
    }
}
like image 372
chrs Avatar asked Dec 05 '25 13:12

chrs


1 Answers

I found the following solution to work. Instead of using firstRectForRange:, which only returns one rect, I use selectionRectsForRange:, and then iterate over all rects and use CGRectUnion to combine them.

- (CGRect)frameOfTextRange:(NSRange)range
{
   UITextPosition *beginning = self.beginningOfDocument;
   UITextPosition *start = [self positionFromPosition: beginning offset: range.location];
   UITextPosition *end = [self positionFromPosition: start offset: range.length];

   UITextRange *textRange = [self textRangeFromPosition: start toPosition: end];

   CGRect  rect = CGRectZero;

   NSArray *selectionRects = [self selectionRectsForRange: textRange];

   for (UITextSelectionRect *selectionRect in selectionRects)
   {
      rect = CGRectUnion(rect, selectionRect.rect);
   }

   return rect;
}
like image 167
koen Avatar answered Dec 07 '25 05:12

koen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!