Zamiennik dla przestarzałego -sizeWithFont: constrainedToSize: lineBreakMode: w iOS 7?


146

W iOS 7 metoda:

- (CGSize)sizeWithFont:(UIFont *)font
     constrainedToSize:(CGSize)size
         lineBreakMode:(NSLineBreakMode)lineBreakMode 

i metoda:

- (CGSize)sizeWithFont:(UIFont *)font

są przestarzałe. Jak mogę wymienić

CGSize size = [string sizeWithFont:font
                 constrainedToSize:constrainSize
                     lineBreakMode:NSLineBreakByWordWrapping];

i:

CGSize size = [string sizeWithFont:font];

2
metoda zastępcza to -sizeWithAttributes:.
holex

ok, dzięki holex, ale jak mogę użyć czcionki z etykiety, takiej jak NSDIctionary? jeśli mój kod to: sizeWithFont: customlabel.font; the void ask "sizeWithAttributes: <# (NSDictionary *) #>"
user_Dennis_Mostajo

1
tutaj jest oficjalna dokumentacja opisująca, jak definiować atrybuty: developer.apple.com/library/ios/documentation/UIKit/Reference/…
holex

Odpowiedzi:


219

Możesz spróbować tego:

CGRect textRect = [text boundingRectWithSize:size
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName:FONT}
                                 context:nil];

CGSize size = textRect.size;

Po prostu zmień „FONT” na „[czcionka UIFont ....]”


13
A gdzie wspominasz o NSLineBreakByWordWrapping? Gdzie to poszło?
user4951

32
NSLineBreakByWordWrappingpójdzie w ciągu NSParagraphStyle. Na przykład: NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;w atrybutach musiałbyś wtedy dodać NSParagraphStyleAttributeName: paragraphStyle.copy...
Florian Friedrich,

1
@ffried w moim przypadku dodanie paragraphStyle z podziałem linii innym niż NSLineBreakByWordWrapping spowodowało obliczenie rozmiaru tylko dla jednej linii… Jakieś myśli?
manicaesar

9
Nie zapominaj, że boundingRectWithSize:options:attributes:context:zwraca wartości ułamkowe. Musisz zrobić ceil(textRect.size.height)i ceil(textRect.size.width)odpowiednio, aby uzyskać rzeczywistą wysokość / szerokość.
Florian Friedrich

20
Co to do cholery jest BOLIVIASize?
JRam13

36

Ponieważ nie możemy użyć sizeWithAttributes dla wszystkich iOS większych niż 4.3, musimy napisać kod warunkowy dla 7.0 i wcześniejszych iOS.

1) Rozwiązanie 1:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
   CGSize size = CGSizeMake(230,9999);
   CGRect textRect = [specialityObj.name  
       boundingRectWithSize:size
                    options:NSStringDrawingUsesLineFragmentOrigin
                 attributes:@{NSFontAttributeName:[UIFont fontWithName:[AppHandlers zHandler].fontName size:14]}
                    context:nil];
   total_height = total_height + textRect.size.height;   
}
else {
   CGSize maximumLabelSize = CGSizeMake(230,9999); 
   expectedLabelSize = [specialityObj.name sizeWithFont:[UIFont fontWithName:[AppHandlers zHandler].fontName size:14] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap]; //iOS 6 and previous. 
   total_height = total_height + expectedLabelSize.height;
}

2) Rozwiązanie 2

UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16]; // Your Font-style whatever you want to use.
gettingSizeLabel.text = @"YOUR TEXT HERE";
gettingSizeLabel.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(310, 9999); // this width will be as per your requirement

CGSize expectedSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

Pierwszym rozwiązaniem jest czasem nie zwrócenie właściwej wartości wysokości. więc użyj innego rozwiązania. który będzie działał idealnie.

Druga opcja jest całkiem dobra i działa płynnie we wszystkich iOS bez kodu warunkowego.


1
dlaczego 230, 999? Skąd masz numer>
user4951

1
230 może być dowolną liczbą. Reprezentuje żądaną szerokość etykiety. 9999 wolałbym raczej zastąpić INFINITY lub MAXFLOAT.
Florian Friedrich

Drugie rozwiązanie działa jak urok. Dzięki, Nirav.
Jim

1
„[AppHandlers zHandler]” wyświetla błąd .. „Niezadeklarowane identyfikatory”. Jak to rozwiązać?
Dimple

9

Oto proste rozwiązanie:

Wymagania:

CGSize maximumSize = CGSizeMake(widthHere, MAXFLOAT);
UIFont *font = [UIFont systemFontOfSize:sizeHere];

Teraz jako constrainedToSizeusage:lineBreakMode:użycie jest przestarzałe w iOS 7.0 :

CGSize expectedSize = [stringHere sizeWithFont:font constrainedToSize:maximumSize lineBreakMode:NSLineBreakByWordWrapping];

Teraz użycie w większej wersji iOS 7.0 będzie:

// Let's make an NSAttributedString first
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:stringHere];
//Add LineBreakMode
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
[attributedString setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle} range:NSMakeRange(0, attributedString.length)];
// Add Font
[attributedString setAttributes:@{NSFontAttributeName:font} range:NSMakeRange(0, attributedString.length)];

//Now let's make the Bounding Rect
CGSize expectedSize = [attributedString boundingRectWithSize:maximumSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;

7

Poniżej znajdują się dwie proste metody, które zastąpią te dwie przestarzałe metody.

A oto odpowiednie referencje:

Jeśli używasz NSLineBreakByWordWrapping, nie musisz określać NSParagraphStyle, ponieważ jest to ustawienie domyślne: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSParagraphStyle_Class/index. html # // apple_ref / occ / clm / NSParagraphStyle / defaultParagraphStyle

Musisz uzyskać górną granicę rozmiaru, aby dopasować wyniki przestarzałych metod. https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSString_UIKit_Additions/#//apple_ref/occ/instm/NSString/boundingRectWithSize:options:attributes:context :

+ (CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font {    
    CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: font}];
    return CGSizeMake(ceilf(size.width), ceilf(size.height));
}

+ (CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
    CGRect textRect = [text boundingRectWithSize:size
                                     options:NSStringDrawingUsesLineFragmentOrigin
                                  attributes:@{NSFontAttributeName: font}
                                     context:nil];
    return CGSizeMake(ceilf(textRect.size.width), ceilf(textRect.size.height));
}

6

W większości przypadków użyłem metody sizeWithFont: constrainedToSize: lineBreakMode: aby oszacować minimalny rozmiar UILabel, aby pomieścić jego tekst (szczególnie, gdy etykieta musi być umieszczona wewnątrz UITableViewCell) ...

... Jeśli tak jest , możesz po prostu użyć metody:

CGSize size = [myLabel textRectForBounds:myLabel.frame limitedToNumberOfLines:mylabel.numberOfLines].size;

Mam nadzieję, że to pomoże.


5
Dokumentacja Apple mówi, że nie powinieneś wywoływać tej metody bezpośrednio.
Barlow Tucker

Nie wspomniano o tym przynajmniej w dokumentacji SDK iOS 7.
Rivera

3
UIFont *font = [UIFont boldSystemFontOfSize:16];
CGRect new = [string boundingRectWithSize:CGSizeMake(200, 300) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: font} context:nil];
CGSize stringSize= new.size;

3
Witamy w StackOverFlow. Nie publikuj ponownie tej samej odpowiedzi. Jeśli chcesz coś dodać do odpowiedzi, wprowadź komentarz lub edytuj odpowiedź.
Ramaraj T

ok .. następnym razem wezmę to pod uwagę. Dziękuję za radę.
user3575114

2

[Zaakceptowana odpowiedź działa ładnie w kategorii. Zastępuję przestarzałe nazwy metod. Czy to dobry pomysł? Wydaje się, że działa bez reklamacji w Xcode 6.x]

Działa to, jeśli cel wdrożenia to 7.0 lub nowszy. Kategoria toNSString (Util)

NSString + Util.h

- (CGSize)sizeWithFont:(UIFont *) font;
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size;

NSString + Util. M

- (CGSize)sizeWithFont:(UIFont *) font {
    NSDictionary *fontAsAttributes = @{NSFontAttributeName:font};
    return [self sizeWithAttributes:fontAsAttributes];
}

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size {
    NSDictionary *fontAsAttributes = @{NSFontAttributeName:font};
    CGRect retVal = [self boundingRectWithSize:size
                                     options:NSStringDrawingUsesLineFragmentOrigin
                                  attributes:fontAsAttributes context:nil];
    return retVal.size;
}

0
UIFont *font = [UIFont fontWithName:@"Courier" size:16.0f];

NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentRight;

NSDictionary *attributes = @{ NSFontAttributeName: font,
                    NSParagraphStyleAttributeName: paragraphStyle };

CGRect textRect = [text boundingRectWithSize:size
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:attributes
                                 context:nil];

CGSize size = textRect.size;

z dwóch odpowiedzi 1 + 2

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.