1

I have a UITextField with some words in it, and I want to figure out the bounding rect for a word at some index.

It's better to give some visual example so I have made a sketch to show what I want.

Let's say I want the bounding rect of "nice" (relative) to the UITextField/UILabel so I would call some method like

[self boundingRectForWordAtIndex:2]

And It would give me the rect you see in the picture

The Demo Picture

rmaddy
  • 314,917
  • 42
  • 532
  • 579
chrs
  • 5,906
  • 10
  • 43
  • 74

1 Answers1

0

I figured it out by using the following code Inspired from the thread: How do I get word wrap information with the new iOS 7 APIs?

- (void)focusOnWordAtIndex:(int)index {
    NSAttributedString *s = [[NSAttributedString alloc] initWithString:self.textField.text
                                                            attributes:@{NSFontAttributeName:self.textField.font}];

    NSTextContainer* tc = [[NSTextContainer alloc] initWithSize:CGSizeMake(CGFLOAT_MAX, self.frame.size.height)];
    tc.lineFragmentPadding = 0.0;
    NSLayoutManager* lm = [NSLayoutManager new];
    NSTextStorage* tm = [[NSTextStorage alloc] initWithAttributedString:s];
    [tm addLayoutManager:lm];
    [lm addTextContainer:tc];
    CGRect wordRect = [lm boundingRectForGlyphRange:[self rangeForWordAtIndex:index] inTextContainer:tc];

// Other code to focus....
}


- (NSRange)rangeForWordAtIndex:(int)index {

    __block NSRange result;
    __block int i = 0;
    NSString *text = self.textField.text;
    [text enumerateSubstringsInRange:NSMakeRange(0, text.length)
                             options:NSStringEnumerationByWords
                          usingBlock:^(NSString *substring,
                                       NSRange substringRange,
                                       NSRange enclosingRange,
                                       BOOL *stop)
    {
        if (i >= index) {
            result = substringRange;
            *stop = YES;
        }
        i++;
    }];

    return result;
}
Community
  • 1
  • 1
chrs
  • 5,906
  • 10
  • 43
  • 74