Как получить NSAttributedString подстроку, которая соответствует определенному прямоугольнику?
Я хочу реализовать ViewControllers, действующие как "приложение Kindle" с помощью UIPageViewController и моего CustomTextViewController.
Но я не могу найти способ получить подстроку NSAttributeString, которая соответствует определенному прямоугольнику.
- У меня есть NSAttributeString из 70000 символов.
- Мой CustomTextViewController имеет один UITextView.
- Он покажет подстроку ATTR_STR_A, просто подходящую по размеру.
- Это означает, что UITextView не нужно прокручивать.
Вот скриншот.
В этом случае последняя строка не видна!!
Подстрока ("До начала ~ Большинство компьютеров предпочли не делать этого") - правильный размер строки.
Как я могу получить эту подстроку или последний индекс подстроки (последний символьный индекс видимой строки, "o" в последнем слове "to")
1 ответ
NSLayoutManager
есть метод, который вы можете найти полезным: enumerateLineFragmentsForGlyphRange:usingBlock:
, С его помощью вы можете перечислять каждую строку текста, получать ее размер и текстовый диапазон внутри textContainer. Итак, все, что вам нужно, это создать экземпляр NSTextStorage
от вашей приписанной строки. Затем создать экземпляр NSTextContainer
с желаемым размером (в вашем случае - CGSizeMake(self.view.frame.width, CGFLOAT_MAX)
, А затем подключите все вещи и начните перечисление. Что-то вроде этого:
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
}];