Die sizeWithFont-Methode ist veraltet. boundingRectWithSize gibt einen unerwarteten Wert zurück

82

In iOS7 sizeWithFontist veraltet, also verwende ich boundingRectWithSize(was einen CGRect-Wert zurückgibt). Mein Code:

 UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

 CGSize maximumLabelSize = CGSizeMake(310, 9999);

 CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                             options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{NSFontAttributeName:fontText}
                             context:nil];

 expectedLabelSize = CGSizeMake(textRect.size.width, textRect.size.height);

In textRectbekomme ich eine Größe größer als meine maximumLabelSize, eine andere Größe als bei der Verwendung sizeWithFont. Wie kann ich dieses Problem beheben?

Nirav Jain
quelle
Ich bekomme dieses Problem mit allen Schriftarten, nicht nur mit Systemschriftarten oder Helvetica.
Nirav Jain
Hast du eine Idee, wie das geht?
Nirav Jain
Ein konkretes Beispiel für Schriftnamen, Text und nicht übereinstimmende Größen kann hilfreich sein.
Eiko
Ich habe CTFramesetterSuggestFrameSizeWithConstraints in iOS6 verwendet, um die Höhe von attributedString zu berechnen, die immer die richtige Höhe zurückgeben. In iOS7 geben sowohl CTFramesetterSuggestFrameSizeWithConstraints als auch boundingRectWithSize ein falsches Höhenergebnis an. Ich wette, es ist ein Fehler, der in iOS7 eingeführt wurde, und es scheint noch keine Lösung zu sein.
Arnold Tang
Ich stehe auch vor dem gleichen Problem, es ist besser, tttattributedlabel
Sri zu verwenden.

Antworten:

151

Wie wäre es mit einem neuen Label erstellen und verwenden sizeThatFit:(CGSize)size?

UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:@"YOUR FONT's NAME" size:16];
gettingSizeLabel.text = @"YOUR LABEL's TEXT";
gettingSizeLabel.numberOfLines = 0;
gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);

CGSize expectSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

Bearbeiten: Dieser obere Code ist nicht für iOS 7 und höher geeignet. Verwenden Sie ihn daher bitte unten:

CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                         options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                         attributes:@{NSFontAttributeName:fontText}
                         context:nil];
Quang Hà
quelle
Diese Methode funktioniert nicht, wenn ich HTML-Entitäten wie (<OL>, <LI>) in Zeichenfolge hinzufüge.
Nirav Jain
Bitte überprüfen Sie meine Antwort noch einmal! Ich habe die numberOfLines-Eigenschaft verpasst! Es tut uns leid!
Quang Hà
1
Nach stundenlangem Suchen, Experimentieren und Sackgassen ist dies die einzige Lösung, die für iOS7 und Xamarin / Monotouch funktioniert
Michael Rodrigues
26
Etikett erstellen, um die Schriftgröße zu berechnen? Das ist so verschwenderisch!
Ossir
13
@Ossir, hast du eine bessere Idee?
Luda
36

Möglicherweise müssen Sie der in dieser Antwort vorgeschlagenen Methode eine zusätzliche Option hinzufügen:

CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                                         options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                      attributes:@{NSFontAttributeName: fontText}
                                         context:nil];
Maxim Pawlow
quelle
3
Es sieht so aus, als wäre das boundingRectWithSizekaputt. Ich habe unter iOS 7, 7.1.1 getestet und es werden nicht korrekte Ergebnisse zurückgegeben.
RaffAl
Dies hat bei mir nicht funktioniert, aber die Verwendung von boundingRectWithSize für einen NSAttributedString und das Hinzufügen meines Schriftattributs zur Zeichenfolge hat stattdessen funktioniert.
Sheepdogsheep
12
Leute, vergessen Sie nicht die Apple-Anweisung: In iOS 7 und höher gibt diese Methode gebrochene Größen zurück (in der Größenkomponente des zurückgegebenen CGRect). Um eine zurückgegebene Ansicht von Größe zu Größe zu verwenden, müssen Sie den Wert mithilfe der Ceil-Funktion auf die nächsthöhere Ganzzahl erhöhen.
SoftDesigner
2
Ceil war nicht genug für mich, fand aber, dass die Verwendung von Ceil und das Hinzufügen von 0,5 den Trick machte
Dwery
15

Hier ist mein Arbeitscode-Snippet:

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:attributeDict];

NSString *headline  = [dict objectForKey:@"title"];  
UIFont *font        = [UIFont boldSystemFontOfSize:18];  
CGRect  rect        = [headline boundingRectWithSize:CGSizeMake(300, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];

CGFloat height      = roundf(rect.size.height +4)

Ich habe der berechneten Höhe 4 Pixel hinzugefügt, da ohne diese 4 Pixel eine Zeile fehlt.

Ich verwende dieses Code-Snippet in einer Tabellenansicht und füge die "Höhe" einem Array von NSNumbers hinzu, und ich erhalte die richtige Zellenhöhe für das Standard-TextLabel.

Fügen Sie 4 weitere Pixel hinzu, wenn Sie mehr Platz unter dem Text im textLabel wünschen.

**** UPDATE ****

Ich bin mit dem "Breitenfehler von 40px" nicht einverstanden, ich rufe die 4px der fehlenden Höhe, weil 4px die Standardhöhe eines Leerzeichens zwischen einem Buchstaben und dem Rand einer einzelnen Zeile ist. Sie können dies mit einem UILabel überprüfen. Für eine Schriftgröße von 16 benötigen Sie eine UILabel-Höhe von 20.

Aber wenn Ihre letzte Zeile kein "g" oder was auch immer enthält, könnte die Messung die 4px Höhe verfehlen.

Ich habe es mit einer kleinen Methode erneut überprüft. Ich erhalte eine genaue Höhe von 20,40 oder 60 für mein Etikett und eine richtige Breite von weniger als 300 Pixel.

Um iOS6 und iOS7 zu unterstützen, können Sie meine Methode verwenden:

- (CGFloat)heightFromString:(NSString*)text withFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    float iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (iosVersion >= 7.0) {
        rect = [text boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
        CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
    }
    NSLog(@"%@: W: %.f, H: %.f", self, rect.size.width, rect.size.height);
    return rect.size.height;
}

**** AKTUALISIERUNG ****

Dank Ihrer Kommentare habe ich meine Funktion wie folgt aktualisiert. Da sizeWithFont veraltet ist und Sie in XCode eine Warnung erhalten, habe ich den Diagnose-Pragma-Code hinzugefügt, um die Warnung für diesen bestimmten Funktionsaufruf / Codeblock zu entfernen.

- (CGFloat)heightFromStringWithFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
        rect = [self boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        CGSize size = [self sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
#pragma GCC diagnostic pop
    }
    return ceil(rect.size.height);
}

Zusätzlich zum 4px-Thema: Je nachdem, welche Schriftart und Schriftgröße Sie verwenden, gibt die Berechnung unterschiedliche Höhenwerte zurück. In meinem Fall: HelveticaNeue-Medium mit einer Schriftgröße von 16,0 gibt eine Zeilenhöhe von 20,0 für eine einzelne Zeile, aber 39,0 für zwei Zeilen zurück, 78 Pixel für 4 Zeilen -> 1 Pixel fehlt für jede Zeile - beginnend mit Zeile 2 - aber Sie möchten Um Ihre Schriftgröße + 4px Zeilenabstand für jede Zeile zu haben, müssen Sie ein Höhenergebnis erhalten.
Bitte beachten Sie dies beim Codieren!
Ich habe noch keine Funktion für dieses "Problem", aber ich werde diesen Beitrag aktualisieren, wenn ich fertig bin.

Rikco
quelle
1
Sie sollten wahrscheinlich [text respondsToSelector: @selector (boundingRectWithSize: options: attribute: context :)] verwenden, anstatt einen Gleitkommawert zu überprüfen.
Samah
1
Es ist besser, die Ceil-Funktion anstelle von + 4pt zu verwenden. Schauen Sie sich diese Antwort an. Stackoverflow.com/a/23563152/667483
surfrider
2

Wenn ich das richtig verstehe, verwenden Sie boundingRectWithSize: Nur um die Größe zu erhalten, die Sie mit sizeWithFont erhalten würden (dh Sie möchten direkt die CGSize, nicht die CGRect)?

Das sieht so aus, wie Sie es suchen:

Ersatz für veraltete GrößeWithFont: in iOS 7?

Sie verwenden sizeWithAttributes:, um die Größe als Ersatz für sizeWithFont zu erhalten.

Erhalten Sie mit so etwas immer noch die falsche Größe:

UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

expectedLabelSize = [myString sizeWithAttributes:@{NSFontAttributeName:fontText}];
vinaut
quelle
aber wie kann ich CGSize maximumLabelSize = CGSizeMake (310, 9999) verwenden? Ich brauche die richtige Höhe und Breite.
Nirav Jain
1
Gibt es Attribute, die sizeWithAttributes mitteilen: um die Breite / Höhe einzuschränken?
Nirav Jain
Entschuldigung, aber ich verstehe nicht, was Ihr Problem ist. Sie möchten das Etikett mit der Schriftgröße dimensionieren, aber nicht mehr als eine maximale Höhe, wenn ich das richtig verstehe. Sie sagen, dass Sie dies mit sizeWithFont tun können, möchten aber jetzt, da diese Methode veraltet ist, eine Alternative, richtig? Sie sollten in der Lage sein, sizeWithAttribues: auf die gleiche Weise anzuschließen, wie Sie sizeWithFont: verwendet haben. Wie haben Sie die Etikettengröße eingeschränkt, als Sie sizeWithFont verwendet haben? Können Sie den Code, der für Sie funktioniert hat, mit sizeWithFont veröffentlichen?
Vinaut
2
Er verwendete sizeWithFont: beschränkteToSize: lineBreakMode: und es gibt keine Möglichkeit, den beschränktenToSize-Wert an sizeWithAttributes zu übergeben.
zh.
2

Der Kommentar von @ SoftDesigner hat bei mir funktioniert

CGRect descriptionRect = [description boundingRectWithSize:CGSizeMake(width, 0)
                                                       options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                    attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}
                                                       context:nil];
result = ceil(descriptionRect.size.height);
Myrddin
quelle
1

Um die Größe der Etikettenlaufzeit zu ermitteln, ist sizewithfont für iOS 7.0 veraltet. Stattdessen müssen Sie -boundingRectWithSize: options: attribute: context: method verwenden

Sie können es wie unten Code verwenden

CGSize constraint = CGSizeMake(MAXIMUM_WIDHT, TEMP_HEIGHT);
NSRange range = NSMakeRange(0, [[self.message body] length]);

NSDictionary *attributes = [YOUR_LABEL.attributedText attributesAtIndex:0 effectiveRange:&range];
CGSize boundingBox = [myString boundingRectWithSize:constraint options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
int numberOfLine = ceil((boundingBox.width) / YOUR_LABEL.frame.size.width);
CGSize descSize = CGSizeMake(ceil(boundingBox.width), ceil(self.lblMessageDetail.frame.size.height*numberOfLine));

CGRect frame=YOUR_LABEL.frame;
frame.size.height=descSize.height;
YOUR_LABEL.frame=frame;

Hier müssen Sie der maximalen Länge Breite geben, um Höhe oder Breite zu ermitteln.

versuchen Sie dies, es funktioniert für mich.

Pratik
quelle