CoreText.Как рассчитать ограничивающую рамку для строки атрибута? - PullRequest
14 голосов
/ 09 августа 2011

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

CTFrameGetVisibleStringRange(rect).length

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

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

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

Спасибо
Дуг

1 Ответ

23 голосов
/ 10 августа 2011

То, что вам нужно, это 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 с, и вы не выпускаете CTFramesetterRef, вы можете иметь серьезные утечки памяти.Обратитесь к учебнику, связанному для получения дополнительной информации об утечках памяти и отладке с помощью инструментов.

Поэтому решение этой проблемы заключается в добавлении CFRelease(frameSetter);

...