How to get an NSAttributedString substring that matches a specific rectangle?

I want ViewControllers to run as a “Kindle app” using UIPageViewController and my CustomTextViewController.

But I cannot find a way to get the substring NSAttributeString that matches the specific rectangle.

  • I have a 70,000 character NSAttributeString.
  • My CustomTextViewController has one UITextView.
  • It will show the substring ATTR_STR_A by simply fitting the size into it.
  • This means that a UITextView does not need to scroll.

Here is a screenshot.

Not

In this case, the last line is not displayed!

The substring ("Before most computers were not chosen for before") is the correct string size.

How can I get this substring or the last index of the substring (the last character index of the visible string, “o” in the last word “before”)

+4
source share
1 answer

NSLayoutManager has a method that you might find useful: enumerateLineFragmentsForGlyphRange:usingBlock: With it, you can list each line of text, get its size and text range inside textContainer. So, all you need to do is create an instance of NSTextStorage from your attribute string. Then create an instance of NSTextContainer with the desired size (in your case, CGSizeMake(self.view.frame.width, CGFLOAT_MAX) ), and then go through all the things and start the listing. Something like that:

 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 }]; 
0
source

All Articles