NSString boundingRectWithSize略微低估了正确的宽度 - 为什么?

exs*_*ape 8 cocoa

我正在创建一个显示带有一些文本的窗口的类,一个"不再显示"复选框和一个按钮.为了可重用,类会根据需要调整窗口大小以适合文本.

但是,在计算中有一些细微的不精确 - 如果我不向宽度添加5个像素,则某些字符串会被截断.(简单地删除了最后一个字.)

这就是我所拥有的:

// NSTextField *textLabel;
// NSString *text;
NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject: [textLabel font] forKey: NSFontAttributeName];
NSRect textFrame = [text boundingRectWithSize:NSMakeSize(textLabel.frame.size.width, (unsigned int)-1)
                                      options:(NSStringDrawingDisableScreenFontSubstitution | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                   attributes:stringAttributes];
textFrame.size.width += 5;
Run Code Online (Sandbox Code Playgroud)

我暂时将标签的背景颜色设置为黄色以使调试更容易,并且它显然扩展到几乎适合最后一个单词.该测试字符串上有4个像素的额外值.
请注意,没有添加这些像素,并非所有字符串都会失败

我关心的原因有两个:
1)我想知道为什么它有点错误,更重要的是
2)我想通过改变计算后的宽度,理论上包装可以改变并且不使用最后一行,在文本下面创建额外的空白区域.

小智 1

在过去的几年里,我多次遇到过同样的问题,每当我需要使用该方法时都会遇到它。我从未找到过任何有关此事的信息,但多年来我收集到的情况是,问题似乎是字符串越短,宽度就越不准确。在足够长的篇幅之后,他们使用的方程几乎是完美的,但在此之前,它是糟糕的。为什么会这样,我从来没有找到解释。

在我尝试解决这个问题时,我尝试添加平面值并乘以常数,但这些从未给出完美的结果。

最近,我一直在使用

width *= (25/(width+2)+1);
Run Code Online (Sandbox Code Playgroud)

与 NSStringDrawingUsesDeviceMetrics。对于我常用的长度来说,这给了我不错的结果。我发现 8-50 个字符之间的字符串的最大差异为 1-2 像素,这足以满足我的要求。50 个字符后,boundingRectWithSize:options:attributes: 更加准确,但并不完美。我还没有对其进行足够广泛的测试,无法说更多。也就是说,这应该消除下面有另一行的担忧,因为文本永远不应该落到另一行。在较高范围内(尚未测试超过 300 个字符),它会稍微高估而不是低估。如果它再次开始低估,请将 25 增加到 ~30。