4

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")

Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
Paul
  • 759
  • 2
  • 7
  • 20
  • @Daij-Djan I have to dynamically change font size, line-spacing and other attributes. I think using table cells has a limit to use my case. – Paul Mar 03 '13 at 12:16
  • sure -- I don't propose a tableview at all here -- from the screenshot I thought you DID use a table – Daij-Djan Mar 04 '13 at 08:34

1 Answers1

1

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
}];
Sega-Zero
  • 3,034
  • 2
  • 22
  • 46