【问题标题】:CoreText. How Do I Calculate the Bounding Box of an Attributed String?核心文本。如何计算属性字符串的边界框?
【发布时间】:2011-10-22 17:49:08
【问题描述】:

在 CoreText 中很容易问:“对于给定的矩形,这个属性字符串可以容纳多少?”。

CTFrameGetVisibleStringRange(rect).length

将返回字符串中下一次文本应该开始的位置。

我的问题是:“给定一个属性字符串和一个宽度,我需要什么矩形高度才能完全绑定属性字符串?”。

CoreText 框架是否提供了执行此操作的工具?

谢谢,
道格

【问题讨论】:

    标签: core-text nsattributedstring


    【解决方案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);
    

    As ARC releases only Objective-C objects,而 CoreText 处理 C,很可能你会在这里发生内存泄漏。如果您的NSAttributedString 很小并且您执行一次,那么您不应该产生任何不良后果。但是如果你有一个循环来计算,比如说,50 个高度的大/复杂NSAttributedStrings,而你不释放CTFramesetterRef,你可能会出现严重的内存泄漏。查看链接的教程,了解有关内存泄漏和使用仪器进行调试的更多信息。

    所以这个问题的解决方法是添加CFRelease(frameSetter);

    【讨论】:

    • 拒绝投票,因为这种方法从未奏效(在 iOS 5 + 6 + 7 中尝试过 - 它在所有 iOS 版本中都有重大错误)。 iOS 6 的错误是臭名昭著的(Apple 虚假地增加宽度、空间不足、删除最后一行高度),但它会做一些愚蠢的事情,比如忽略字形并假设每个字符都是“f”或“g”,尽管有输入参数以防止出现该问题。
    • 这种方法众所周知是有问题的
    猜你喜欢
    • 2012-03-21
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    相关资源
    最近更新 更多