How to get NSAttributedString substring that fit specific rect?

1.1k Views Asked by At

I want a implement ViewControllers acting like a "Kindle App" by using UIPageViewController and my CustomTextViewController.

But I can't find a way to get substring of NSAttributeString that fit specific rect.

  • I have a NSAttributeString of 70,000 characters.
  • My CustomTextViewController has a one UITextView.
  • It will show substring of ATTR_STR_A, just fit in it's size.
  • It means UITextView don't have to scroll.

Here is a screenshot.

Not

In this case last line is not visible!!

Substring ("Before the early ~ Most computers opted not to") is a right size of string.

How can I get a that substring, or last index of substring ( last character index of visible line, "o" in last word "to")

1

There are 1 best solutions below

0
On

NSLayoutManager has a method you may find useful: enumerateLineFragmentsForGlyphRange:usingBlock:. With help of it you can enumerate each line of text, get it's size and a text range within a textContainer. So, all you need is to instantiate NSTextStorage from your attributed string. Then, instantiate NSTextContainer with a desired size (in your case - CGSizeMake(self.view.frame.width, CGFLOAT_MAX). And then wire all the things up and start the enumeration. Something like this:

NSTextStorage *textStorage =  [[NSTextStorage alloc] initWithAttributedString:attrString];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(self.view.frame.width, CGFLOAT_MAX)];
NSLayoutManager *layoutManager = [NSLayoutManager new];

[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];

NSRange allRange = NSMakeRange(0, textStorage.length);

//force layout calculation
[layoutManager ensureLayoutForTextContainer:textContainer];

[layoutManager enumerateLineFragmentsForGlyphRange:allRange usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer * _Nonnull textContainer, NSRange glyphRange, BOOL * _Nonnull stop) {
    //here you can do anything with the info: bounds of text, text range, line number etc
}];