Замена устаревшего -sizeWithFont: constrainedToSize: lineBreakMode: в iOS 7?

В iOS 7 метод:

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

и метод:

- (CGSize)sizeWithFont:(UIFont *)font

устарели. Как мне заменить

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

и:

CGSize size = [string sizeWithFont:font];

person user_Dennis_Mostajo    schedule 19.09.2013    source источник
comment
метод замены - -sizeWithAttributes:.   -  person holex    schedule 20.09.2013
comment
хорошо holex, спасибо, но как я могу использовать шрифт с лейбла, например NSDIctionary? если мой код похож на: sizeWithFont: customlabel.font; недействительный запрос sizeWithAttributes: ‹# (NSDictionary *) #›   -  person user_Dennis_Mostajo    schedule 20.09.2013
comment
вот официальная документация по определению атрибутов: developer.apple.com/library/ios/documentation/UIKit/Reference/   -  person holex    schedule 20.09.2013


Ответы (8)


Вы можете попробовать это:

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

CGSize size = textRect.size;

Просто замените "FONT" на "[шрифт UIFont ....]"

person Xavier Maroñas    schedule 23.09.2013
comment
А где вы упомянули NSLineBreakByWordWrapping? Куда оно делось? - person user4951; 04.11.2013
comment
NSLineBreakByWordWrapping войдет в NSParagraphStyle. Так, например: NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; В атрибутах вам нужно будет добавить _4 _... - person Florian Friedrich; 19.12.2013
comment
@ffried в моем случае добавление абзаца с разрывом строки, отличным от NSLineBreakByWordWrapping, привело к вычислению размера только для одной строки ... Есть мысли? - person manicaesar; 03.02.2014
comment
@manicaesar За исключением NSLineBreakByWordWrapping и NSLineBreakByCharWrapping, все режимы разрыва строки создаются только для одной строки (путем усечения строки). Я только что протестировал его, и все режимы разрыва строки работают, как ожидалось. - person Florian Friedrich; 03.02.2014
comment
Не забывайте, что boundingRectWithSize:options:attributes:context: возвращает дробные значения. Вам нужно сделать ceil(textRect.size.height) и ceil(textRect.size.width) соответственно, чтобы получить реальную высоту / ширину. - person Florian Friedrich; 03.02.2014
comment
Хм, вы правы, наличие (например) NSLineBreakModeByTruncatingMiddle не имеет смысла для нескольких строк. Если кто-то хочет, чтобы последняя строка была обрезана, он может использовать NSStringDrawingTruncatesLastVisibleLine. Спасибо! - person manicaesar; 03.02.2014
comment
Возвращает ли это тот же размер, что и sizeWithFont? Я столкнулся с этой проблемой, и при использовании вышеуказанного метода разница в высоте по-прежнему составляет от 3 до 4 пикселей, что вызывает большую разницу в пользовательском интерфейсе для iOS 6.0 и iOS 7.0 при сравнении бок о бок. - person Javal Nanda; 19.02.2014
comment
boundingRectWithSize не возвращает правильную ширину и высоту. - person Nirav Jain; 05.03.2014
comment
Что, черт возьми, такое BOLIVIASize? - person JRam13; 04.06.2014
comment
boundingRectWithSize по-прежнему возвращает неправильный результат, когда я его тестирую. Сценарий - это когда вы тестируете длинные и множественные абзацы. - person Nirav Jain; 02.07.2014
comment
@Nirav Я столкнулся с той же проблемой для длинного абзаца, но после исследования проблемы я обнаружил, что я не предоставляю точные атрибуты, такие как размер шрифта. Было 12 и должно быть 14, как в конструкторе интерфейсов в моем случае. - person Sawsan; 07.07.2014
comment
NSLineBreakByWordWrapping представлен NSStringDrawingUsesLineFragmentOrigin. - person Marius Soutier; 21.09.2014

Поскольку мы не можем использовать sizeWithAttributes для всех iOS выше 4.3, мы должны написать условный код для 7.0 и предыдущих версий iOS.

1) Решение 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) Решение 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];

Первое решение: иногда не удается вернуть правильное значение высоты. так что используйте другое решение. который будет работать отлично.

Второй вариант неплох и безотказно работает на всех iOS без условного кода.

person Nirav Jain    schedule 02.10.2013
comment
почему 230, 999? Где взять номер › - person user4951; 04.11.2013
comment
230 может быть любым числом. Он представляет желаемую ширину этикетки. 9999 я бы предпочел заменить на INFINITY или MAXFLOAT. - person Florian Friedrich; 19.12.2013
comment
Второе решение работает как шарм. Спасибо, Нирав. - person Jim; 02.05.2014
comment
[AppHandlers zHandler] выдает ошибку .. Необъявленные идентификаторы. Как это решить? - person Dimple; 06.05.2014

Вот простое решение:

Требования :

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

Теперь, поскольку constrainedToSizeusage:lineBreakMode: использование не рекомендуется в iOS 7.0:

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

Теперь использование в более поздней версии iOS 7.0 будет:

// 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;
person Paresh Navadiya    schedule 23.06.2014

Ниже приведены два простых метода, которые заменят эти два устаревших метода.

И вот соответствующие ссылки:

Если вы используете NSLineBreakByWordWrapping, вам не нужно указывать NSParagraphStyle, так как это значение по умолчанию: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSParagraphStyle_Class/index.html#//apple_ref/occ/clm/NSParagraphStyle/defaultParagraphStyle

Вы должны получить потолок размера, чтобы соответствовать результатам устаревших методов. 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));
}
person Elijah    schedule 06.01.2015

В большинстве случаев я использовал метод sizeWithFont: constrainedToSize: lineBreakMode: для оценки минимального размера UILabel для размещения его текста (особенно когда метка должна быть размещена внутри UITableViewCell) ...

... Если это именно ваша ситуация, вы можете просто использовать метод:

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

Надеюсь, это поможет.

person roberto.buratti    schedule 08.10.2013
comment
В документации Apple сказано, что вы не должны вызывать этот метод напрямую. - person Barlow Tucker; 24.10.2013
comment
По крайней мере, не упоминается в документации iOS 7 SDK. - person Rivera; 21.01.2014

[Принятый ответ отлично работает в категории. Я перезаписываю устаревшие имена методов. Это хорошая идея? Кажется, работает без жалоб в Xcode 6.x]

Это работает, если ваша цель развертывания 7.0 или выше. Категория NSString (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;
}
person Dan Rosenstark    schedule 28.09.2015

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;

из двух ответов 1 + 2

person Alex    schedule 18.07.2017

person    schedule
comment
Добро пожаловать в StackOverFlow. Не публиковать один и тот же ответ снова. Если вам нужно что-то добавить к ответу, оставьте комментарий или отредактируйте ответ. - person Ramaraj T; 18.07.2014
comment
хорошо .. Я учту это в следующий раз. Спасибо за ваш совет. - person user3575114; 18.07.2014