使用自定义字体计算NSString的高度

Ama*_*ulo 5 objective-c ios

我正试图解决这个问题一个星期了,我已经测试了很多想法,但我无法正确计算NSString自定义字体的大小.

我有UITextView一个文本和一个UIView我在其中绘制行的行号UITextView.问题是,NSString UIKit在计算尺寸时,Additions忽略了标签宽度NSString.

在图片中你可以清楚地看到第7行,它在渲染时是换行符UITextView,之后所有行都受到影响.

模拟器截图

我使用的字体是Adobe Source Code Pro.

我尝试过NSString UIKitAdditions的所有方法都没有成功.

sizeWithFont

sizeWithFont:forWidth:lineBreakMode:

sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:
Run Code Online (Sandbox Code Playgroud)

我也尝试用四个空格替换字符串中的所有选项卡,这有帮助,但它仍然不能一直工作.对于某些线路它有帮助,但对某些线路没有帮助.

有关如何NSString正确计算身高的建议吗?CoreText也许?

一个小笔记.我试图通过使用UITextInput协议中的几何命中测试方法解决这个问题,当它们正在工作时,cpu加载在模拟器上是100%,所以在真实设备上它会杀死应用程序,特别是如果我加载大约1500+的文件代码行.

这里是我用于LineNumbersView.m的代码的要点.

Tom*_*mmy 1

假设UITextView和 Core Text 总是完全一致,那么后者绝对是一个解决方案,尽管对于这个问题来说并不是非常简单。

你:

  1. 在主视图中创建文本的属性字符串,并在整个范围内设置适当的字体;
  2. 为属性字符串创建合适的框架设置器(使用CTFramesetterCreateWithAttributedString);
  3. 创建一个CGPath,描述字符串将被绘制到的绘图区域(作为 aUIBezierPath然后获取CGPath属性,或者创建一个并使用CGPathAddRect);
  4. 因此,从框架设置器加上路径加上您感兴趣的字符串的子范围创建一个框架,这可能就是全部(请参阅CTFramesetterCreateFrame);
  5. 然后,您可以从框架中获取CFArray它将输出的各个行(使用CTFrameGetLines),尽管这些是屏幕上的排版行而不是源代码行;
  6. 对于每一行,您都可以获取它包含的原始字符串的范围(使用CTLineGetStringRange),从而允许您确定哪些是在原始换行符之后立即开始的,而不是由于自动换行而开始;
  7. 您还可以获得CGPoints 的 C 数组,其中每个代表屏幕上一条线的原点 ( CTFrameGetLineOrigins);通过使用您在 (6) 中学到的知识来查找位置,您可以获得相关线条的屏幕原点。

为了增加乐趣,Core Text 的像素输出在 OS X 和 iOS 上是相同的。然而,OS X 认为屏幕的原始位置是左下角,就像方格纸一样。iOS 认为它位于左上角,就像英文阅读顺序一样。粗略表述的最终效果是在 iOS 上 Core Text 绘制颠倒。所以你需要考虑到这一点。在 iOS 术语中,您显然会看到第一行位于框架的最底部,第二行位于其上方的一行,依此类推。您需要翻转这些坐标。

即使您跳过了这么多的麻烦,它最终可能只有一百行左右的代码。