NSString boundingRectWithSize返回不必要的高度

当使用[NSString boundingRectWithSize:options:attributes] ,返回的矩形的大小比我预期的某些string更高。 返回的高度似乎表示具有给定属性的string的最大可能高度,而不是string本身的高度。

假设具有相同的属性和选项,string“ cars ”返回的高度与string“ ÉTAS-UNIS ”返回的高度相同(请注意E上的重音)。

我会期望boundingRectWithSize只考虑给定的string中的字符,在我看来,它会返回一个较短的高度string“ cars ”。

在附加的屏幕截图中,我已经填充了从boundingRectWithSize返回的矩形,并用红色标出了我将假定边界矩形应该是什么的。 矩形的宽度与我所期望的相当,但是高度比我预期的要高得多。 这是为什么?

Bounding Rect示例

示例代码:

 NSRect boundingRect = NSZeroRect; NSSize constraintSize = NSMakeSize(CGFLOAT_MAX, 0); NSString *lowercaseString = @"cars"; NSString *uppercaseString = @"ÉTAS-UNIS"; NSString *capitalizedString = @"Japan"; NSFont *drawingFont = [NSFont fontWithName:@"Georgia" size:24.0]; NSDictionary *attributes = @{NSFontAttributeName : drawingFont, NSForegroundColorAttributeName : [NSColor blackColor]}; boundingRect = [lowercaseString boundingRectWithSize:constraintSize options:0 attributes:attributes]; NSLog(@"Lowercase rect: %@", NSStringFromRect(boundingRect)); boundingRect = [uppercaseString boundingRectWithSize:constraintSize options:0 attributes:attributes]; NSLog(@"Uppercase rect: %@", NSStringFromRect(boundingRect)); boundingRect = [capitalizedString boundingRectWithSize:constraintSize options:0 attributes:attributes]; NSLog(@"Capitalized rect: %@", NSStringFromRect(boundingRect)); 

输出:

 Lowercase rect: {{0, -6}, {43.1953125, 33}} Uppercase rect: {{0, -6}, {128.44921875, 33}} Capitalized rect: {{0, -6}, {64.5, 33}} 

您可能想在选项中使用NSStringDrawingUsesDeviceMetrics 。 从文档 :

NSStringDrawingUsesDeviceMetrics

计算布局时使用图像字形边界(而不是印刷边界)。

@omz仍然因为为我工作而获得功劳。 他的回答让我更多的看CoreText,因为我认为像boundingRectWithSize最终调用CoreText函数。

在WWDC 2012的第226期会议中,有一整段专门用来计算一条线的度量,令我吃惊的是,他们谈到了一个名为CTLineGetBoundsWithOptions的新的CoreText函数。

据我所知,该方法只logging在CTLine.hCoreText Changes文档中。 在文档中进行正常search时,它肯定不会出现(对我来说)。

但它似乎工作,并在我的testing它返回完全相同的结果作为我的系统上安装的所有字体boundingRectWithSize 。 更好的是,它比boundingRectWithSize快了将近2倍。

正如WWDC的video所提到的,为什么你需要计算一个string的边界而不考虑线高度等事情,但是如果你确实需要这样做的话,那么我觉得这可能是最好的方法使用。 一如既往,YMMV。

粗略的示例代码:

 NSFont *font = [NSFont systemFontOfSize:13.0]; NSDictionary *attributes = @{(__bridge NSString *)kCTFontAttributeName : font}; NSAttributedString *attributeString = [[NSAttributedString alloc] initWithString:self.text attributes:attributes]; CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)attributeString); CGRect bounds = CTLineGetBoundsWithOptions(line, kCTLineBoundsUseGlyphPathBounds); CFRelease(line); return NSRectFromCGRect(bounds); 

我尝试了boundingRectWithSize函数,但它没有为我工作。

什么工作是sizeThatFits

用法:

 CGSize maxSize = CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX) CGSize size = [myLabel sizeThatFits:maxSize];