web-dev-qa-db-fra.com

La méthode sizeWithFont est obsolète. boundingRectWithSize renvoie une valeur inattendue

Dans iOS7, sizeWithFont est obsolète. J'utilise donc boundingRectWithSize (qui renvoie une valeur CGRect). Mon 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);

Dans textRect, je reçois une taille supérieure à celle de mon maximumLabelSize, une taille différente de celle utilisée lors de l'utilisation de sizeWithFont. Comment puis-je résoudre ce problème?

79
Nirav

Pourquoi ne pas créer une nouvelle étiquette et utiliser 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];

Edit: Ce code supérieur n'est pas bon pour iOS 7 et supérieur, utilisez donc ci-dessous:

CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                         options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                         attributes:@{NSFontAttributeName:fontText}
                         context:nil];
148
Quang Hà

Peut-être devriez-vous fournir une option supplémentaire à la méthode suggérée dans this answer:

CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                                         options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                      attributes:@{NSFontAttributeName: fontText}
                                         context:nil];
35
Maxim Pavlov

Voici mon extrait de code de travail:

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)

J'ai ajouté 4px à la hauteur calculée, car sans ces 4px, il manque une ligne.

J'utilise cet extrait de code dans une table et ajoute la "hauteur" à un tableau de NSNumbers et j'obtiens la hauteur de cellule correcte pour le libellé par défaut textLabel.

Ajoutez 4 pixels supplémentaires si vous voulez plus d’espace sous le texte dans le libellé textLabel.

**** MISE À JOUR ****

Je ne suis pas d'accord avec le "bug de largeur de 40px", je crie être le 4px de hauteur manquante, car 4px est la hauteur par défaut d'un espace entre une lettre et la limite d'une seule ligne. Vous pouvez le vérifier avec un UILabel. Pour une taille de police de 16, vous avez besoin d’une hauteur UILabel de 20.

Mais si votre dernière ligne n'a pas de "g" ou quoi que ce soit dedans, la mesure pourrait être manquante les 4 pixels de hauteur.

Je l'ai revérifié avec un peu de méthode, j'ai une hauteur précise de 20,40 ou 60 pour mon étiquette et une largeur droite inférieure à 300 px.

Pour prendre en charge iOS6 et iOS7, vous pouvez utiliser ma méthode:

- (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;
}

**** MISE À NIVEAU ****

Grâce à vos commentaires, j'ai amélioré ma fonction comme suit. Puisque sizeWithFont est obsolète et que vous obtiendrez un avertissement dans XCode, j'ai ajouté le diagnostic-pragma-code pour supprimer l'avertissement relatif à cet appel de fonction/bloc de code particulier.

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

Outre la rubrique 4px: en fonction de la police et de l'épaisseur de police que vous utilisez, le calcul renvoie différentes valeurs de hauteur. Dans mon cas: HelveticaNeue-Medium avec une taille de police de 16,0 renvoie une hauteur de ligne de 20,0 pour une seule ligne mais 39,0 pour deux lignes, 78px pour 4 lignes -> 1px manquant pour chaque ligne - à partir de la ligne 2 - mais vous voulez pour avoir votre fontsize + 4px linespace pour chaque ligne, vous devez obtenir un résultat en hauteur.
S'il vous plaît gardez cela à l'esprit lors du codage!
Je n'ai pas encore de fonction pour ce "problème" mais je mettrai à jour ce post lorsque j'aurai terminé.

15
Rikco

Si je comprends bien, vous utilisez boundingRectWithSize: simplement pour obtenir la taille que vous obtiendriez avec sizeWithFont (ce qui signifie que vous voulez directement le CGSize, pas le CGRect)?

Cela ressemble à ce que vous recherchez:

Remplacement pour obsolète sizeWithFont: dans iOS 7?

Ils utilisent sizeWithAttributes: pour obtenir la taille, en remplacement de sizeWithFont.

Avez-vous toujours la mauvaise taille en utilisant quelque chose comme ceci:

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

expectedLabelSize = [myString sizeWithAttributes:@{NSFontAttributeName:fontText}];
2
vinaut

Le commentaire de @ SoftDesigner a fonctionné pour moi

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

pour trouver la taille du temps d'exécution de l'étiquette sizewithfont est obsolète pour iOS 7.0 au lieu de cela, vous devez utiliser - boundingRectWithSize: options: attributs: contexte: méthode

vous pouvez l'utiliser comme ci-dessous le code

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;

ici, vous devez donner la largeur maximale à la largeur pour trouver la hauteur ou la largeur.

essayez ceci cela fonctionne pour moi.

1
Pratik