Подтвердить что ты не робот

CoreText. Как вычислить ограниченную ячейку атрибутной строки?

В CoreText легко спросить: "для данного прямоугольника, сколько этой атрибутной строки будет соответствовать?".

CTFrameGetVisibleStringRange(rect).length

Вернется туда, где в строке должен начаться следующий запуск текста.

Мой вопрос: "Приписываемая строка и ширина, какая высота высоты мне нужна, чтобы полностью связать атрибутную строку?".

Предоставляет ли среда CoreText инструменты для этого?

Спасибо,
Дуг

4b9b3361

Ответ 1

Вам нужно CTFramesetterSuggestFrameSizeWithConstraints(), вы можете использовать его так:

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attributedString)); /*Create your framesetter based in you NSAttrinbutedString*/
CGFloat widthConstraint = 500; // Your width constraint, using 500 as an example
CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(
   framesetter, /* Framesetter */
   CFRangeMake(0, text.length), /* String range (entire string) */
   NULL, /* Frame attributes */
   CGSizeMake(widthConstraint, CGFLOAT_MAX), /* Constraints (CGFLOAT_MAX indicates unconstrained) */
   NULL /* Gives the range of string that fits into the constraints, doesn't matter in your situation */
);
CGFloat suggestedHeight = suggestedSize.height;

ИЗМЕНИТЬ

//IMPORTANT: Release the framesetter, even with ARC enabled!
CFRelease(frameSetter);

Поскольку ARC выпускает только Objective-C объекты, а CoreText имеет дело с C, очень вероятно, что здесь может быть утечка памяти. Если ваш NSAttributedString невелик, и вы делаете это один раз, вы не должны иметь никаких плохих последствий. Но в случае, если у вас есть цикл для вычисления, допустим, 50 высот больших/сложных NSAttributedString s, и вы не выпускаете CTFramesetterRef, у вас могут быть серьезные утечки памяти. Проверьте связанный учебник для получения дополнительной информации об утечках памяти и отладки с помощью инструментов.

Итак, решение этой проблемы состоит в том, чтобы добавить CFRelease(frameSetter);