2014-01-22 4 views
17

Bei Verwendung von [NSString boundingRectWithSize:options:attributes] ist die Größe des zurückgegebenen Rectals höher als bei bestimmten Strings. Die zurückgegebene Höhe scheint die maximal mögliche Höhe einer Zeichenfolge mit den angegebenen Attributen und nicht die Höhe der Zeichenfolge selbst darzustellen.NSString boundingRectWithSize, das unnötig hohe Höhe zurückgibt

Unter der Annahme der gleichen Attribute und Optionen ist die für die Zeichenfolge "cars" zurückgegebene Höhe die gleiche Höhe, die für die Zeichenfolge "ÉTAS-UNIS" zurückgegeben wird (beachten Sie den Akzent auf dem E).

Ich hätte erwartet boundingRectWithSize, nur die Zeichen in der gegebenen Zeichenfolge zu berücksichtigen, die meiner Meinung nach eine kürzere Höhe für die Zeichenfolge "cars" zurückgegeben haben würde.

In den angehängten Screenshots habe ich das von boundingRectWithSize zurückgegebene Rechteck ausgefüllt und rot umrissen, was ich angenommen hätte, dass der Bounding Rect hätte sein sollen. Die Breite des Rect ist so ziemlich wie ich es erwarten würde, aber die Höhe ist wesentlich höher als ich erwartet hätte. Warum das?

Bounding Rect Example

Beispielcode:

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)); 

Ausgang:

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

Bitte überprüfen Sie die Antwort auf die ähnliche Frage hier- [http://stackoverflow.com/a/27289303/591811][1] [1]: http://stackoverflow.com/a/27289303/591811 – shoan

Antwort

25

Vielleicht möchten NSStringDrawingUsesDeviceMetrics in den Optionen verwenden. Vom docs:

NSStringDrawingUsesDeviceMetrics

Verwenden Sie die Bild Glyphe Grenzen (statt der typographischen Grenzen) bei der Berechnung Layout.

+0

ich war so gut wie sicher ich versucht habe, die Flagge, aber ich glaube, ich immer versucht, würde es neben der 'NSStringDrawingUsesLineFragmentOrigin' Flagge, was tat nicht die Ergebnisse, die ich wollte. Alleine benutzt, tut es. Vielen Dank. Es scheint bemerkenswert schwierig zu sein, hinter einem abgeschnittenen Text ein perfektes Rechteck zu zeichnen. Die Anfrage nach dem umschließenden Rect mit 'NSStringDrawingUsesLineFragmentOrigin' enthält" padding ", aber dieses Flag wird benötigt, damit' NSStringDrawingTruncatesLastVisibleLine' verwendet werden kann. – kennyc

4

@omz bekommt immer noch Anerkennung dafür, dass diese Arbeit für mich funktioniert. Seine Antwort brachte mich dazu, mich in CoreText umzuschauen, da ich annehme, dass etwas wie boundingRectWithSize letztendlich eine CoreText-Funktion aufruft.

In der Sitzung 226 von WWDC 2012 gab es einen ganzen Abschnitt, der der Berechnung der Metriken einer Linie gewidmet war. Zu meiner Überraschung sprachen sie über eine neue CoreText-Funktion namens .

Soweit ich das beurteilen kann, ist diese Methode nur in CTLine.h und im CoreText Changes Dokument dokumentiert. Bei einer normalen Suche in der Dokumentation fällt es mir sicher nicht auf.

Aber es scheint zu funktionieren und in meinen Tests gibt es genau das gleiche Ergebnis wie boundingRectWithSize für alle Schriftarten auf meinem System installiert. Noch besser ist, dass es fast 2x schneller zu sein scheint als boundingRectWithSize. Wie das WWDC-Video erwähnt, ist es ein wenig unklar, warum Sie die Grenzen einer Zeichenkette berechnen müssen, ohne Dinge wie die Zeilenhöhe zu berücksichtigen, aber wenn Sie das tun müssen, dann denke ich, dass dies der Fall sein könnte die beste Methode zu verwenden. Wie immer, YMMV.

Raue Beispielcode:

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); 
+0

"CTLineGetBoundsWithOptions" wird auch im Dokument "Was ist neu" für OS 10.8 erwähnt. – JWWalker

+1

Vielen Dank für die Erwähnung von CTLineGetBoundsWithOptions liefert die richtige Textgröße, während boundingRectWithSize: Optionen: Kontext: gibt mir die doppelte Höhe in iOS 8. Total komisch. Jetzt ist es an der Zeit herauszufinden, wie der Text umbrochen werden soll. – Ben

+0

Ich sehe iOS8 doppelte Höhe des berechneten Textes, auch unabhängig von den Optionen, die ich einstelle. CTLineGetBoundsWithOptions funktioniert wie ein Zauber. – u2Fan

0

Ich versuchte, die boundingRectWithSize Funktion, aber es hat nicht für mich zu arbeiten.

Was tat Arbeit war sizeThatFits

Verbrauch:

CGSize maxSize = CGSizeMake(myLabel.frame.size.width, CGFLOAT_MAX) 

CGSize size = [myLabel sizeThatFits:maxSize]; 
+0

Die Frage ist sowohl als iOS als auch als OSX markiert, aber ich denke 'sizeThatFits:' ist nur für iOS verfügbar. – JWWalker