Подтвердить что ты не робот

'sizeWithFont: constrainedToSize: lineBreakMode:' устарел:

Преобразование проекта с iOS5.0 в iOS7/iOS6 на Xcode 5. В приведенном ниже коде дается предупреждение о времени компиляции:

'sizeWithFont: constrainedToSize: lineBreakMode:' устарел: сначала устарел в ios 7.0 - Use - boundingRectWithSize: options: attribiutes: context

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0)
    {
        self.lblHidden.frame = CGRectMake(58, 228, 945, 9999);
        self.lblHidden.text = detailShareObj.pDesc;
        CGSize size = [detailShareObj.pDesc sizeWithFont:self.lblHidden.font constrainedToSize:self.lblHidden.frame.size lineBreakMode:NSLineBreakByWordWrapping];
        return 228.0+size.height+20;

    }
    else if (indexPath.section == 1)
    {
        NSString *tempPointStr = (self.shortDescArray)[indexPath.row];

        self.lblHidden.frame = CGRectMake(58, 0, 945, 9999);
        self.lblHidden.text = tempPointStr;
        CGSize size = [tempPointStr sizeWithFont:self.lblHidden.font
                               constrainedToSize:self.lblHidden.frame.size
                                   lineBreakMode:NSLineBreakByWordWrapping];

            return 50.0f;
    }

Я попробовал некоторое предложение в другом месте, но ничего не спасает, если кто-то может помочь, если внести исправления, требуемые в коде, будет с благодарностью.

4b9b3361

Ответ 1

Я бы не просто маскировал предупреждение устаревшей функции. Они не одобряли это по какой-то причине. Я считаю, что функция была устаревшей, потому что эта серия функций NSString + UIKit была основана на библиотеке UIStringDrawing, которая не была потокобезопасной. Если вы попытались запустить их не в основном потоке (как и любая другая функция UIKit), вы получите непредсказуемое поведение. В частности, если вы запускаете функцию на нескольких потоках одновременно, это, вероятно, приведет к краху вашего приложения. Вот почему в iOS 6 они внедрили метод boundingRectWithSize:... для NSAttributedStrings. Это было построено поверх библиотек NSStringDrawing и является потокобезопасным.

Если вы посмотрите на новую функцию NSString boundingRectWithSize:..., она запрашивает массив атрибутов таким же образом, как и NSAttributeString. Если бы мне пришлось догадаться, эта новая функция NSString в iOS 7 является просто оболочкой для функции NSAttributeString от iOS 6.

В этой заметке, если вы поддерживали только iOS 6 и iOS 7, я бы определенно изменил все ваши NSString sizeWithFont:... на NSAttributeString boundingRectWithSize. Это сэкономит вам много головной боли, если у вас будет странный многопоточный угловой футляр! Вот как я преобразовал NSString sizeWithFont:constrainedToSize::

Раньше:

NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
CGSize size = [text sizeWithFont:font 
               constrainedToSize:(CGSize){width, CGFLOAT_MAX}];

Можно заменить на:

NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
NSAttributedString *attributedText =
    [[NSAttributedString alloc]
        initWithString:text
        attributes:@
        {
            NSFontAttributeName: font
        }];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];
CGSize size = rect.size;

Обратите внимание, что в документации упоминается:

В iOS 7 и более поздних версиях этот метод возвращает дробные размеры (в размере компонент возвращаемого CGRect); использовать возвращаемый размер по размеру просмотров, вы должны использовать, чтобы повысить его значение до ближайшего более высокого целого используя функцию ceil.

Чтобы вытащить вычисленную высоту или ширину, которые будут использоваться для определения размеров, я бы использовал:

CGFloat height = ceilf(size.height);
CGFloat width  = ceilf(size.width);

Ответ 2

Если вы хотите, чтобы он был совместим как с iOS7, так и с версиями ниже, попробуйте этот (с ARC):

CGSize size;

if ([tempPointStr respondsToSelector:
     @selector(boundingRectWithSize:options:attributes:context:)])
{
  NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
  paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
  paragraphStyle.alignment = NSTextAlignmentLeft;

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

  size = [tempPointStr boundingRectWithSize:self.lblHidden.frame.size
                                    options:NSStringDrawingUsesFontLeading
                                           |NSStringDrawingUsesLineFragmentOrigin
                                 attributes:attributes
                                    context:nil].size;
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
  size = [tempPointStr sizeWithFont:self.lblHidden.font
                  constrainedToSize:self.lblHidden.frame.size
                      lineBreakMode:NSLineBreakByWordWrapping];
#pragma clang diagnostic pop
}

Примечание. Это просто пример для вашего случая else-if, возможно, вам нужно сделать некоторые изменения в зависимости от того, кем вы хотите.;)

Ответ 3

Для iOS7 замените:

CGSize size = [tempPointStr sizeWithFont:self.lblHidden.font
                       constrainedToSize:self.lblHidden.frame.size
                           lineBreakMode:NSLineBreakByWordWrapping];

С

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; //set the line break mode
NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys:self.lblHidden.font, NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
CGSize size = [tempPointStr boundingRectWithSize:self.lblHidden.frame.size
                                         options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin
                                      attributes:attrDict context:nil].size;

Ответ 4

Вы можете использовать:

UIFont *font = [UIFont boldSystemFontOfSize:16];

CGRect new = [string boundingRectWithSize:CGSizeMake(200, 300)
    options:NSStringDrawingUsesFontLeading 
    attributes:@{NSFontAttributeName: font} 
    context:nil];

CGSize stringSize= new.size;

Ответ 5

Если вы ориентируетесь на iOS 6.0+, вы все равно можете использовать sizeWithFont:constrainedToSize:lineBreakMode:. Просто убедитесь, что для вашего проекта iOS Deployment Target установлено значение 6.0, и компилятор не даст вам этих предупреждений.

(Вы можете найти это, щелкнув вкладку синего проекта (обычно вверху слева, панель навигации проекта) в разделе "информация" ).

Если вы ориентируетесь только на iOS 7.0+, вы должны использовать новый метод boundingRectWithSize:options:attributes:context.

Вы можете найти документы Apple по этому новому методу.

Ответ 6

ОграничивающийRectWithSize: options: attributes: контекст имеет проблему, что он не правильно вычисляет высоту, если строка содержит "\n" (разрывы строк). Поэтому этот код вычисляет размер для каждой строки отдельно для заданной ширины (inWidth):

NSArray *brokenByLines=[string componentsSeparatedByString:@"\n"];
CGFloat height=0.0;
CGFloat maxWidth=0.0;
for (NSString* actString in brokenByLines) {
    CGRect tSize=[actString boundingRectWithSize:CGSizeMake(inWidth, 600) options:(NSStringDrawingUsesLineFragmentOrigin | NSLineBreakByWordWrapping) attributes:@{NSFontAttributeName: inFont} context:nil];
    if (maxWidth<tSize.size.width) {
        maxWidth=tSize.size.width;
    }
    height+=tSize.size.height;
}
CGSize size= CGSizeMake(ceil(maxWidth), ceil(height));