SizeWithFont: constrainedToSize: lineBreakMode: устарел в iOS7

Я обновляю свое приложение до iOS 7 и, наконец, получил его, но там одна вещь, на которую я не могу найти решение.

В Xcode 4 я использовал следующий метод:

#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 280.0f
#define CELL_CONTENT_MARGIN 10.0f


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; {
    NSString *text = [textA objectAtIndex:[indexPath row]];

    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];

    CGFloat height = MAX(size.height, 28.0f);

    return height + (CELL_CONTENT_MARGIN * 2);
}

Но я получаю сообщение об ошибке при его использовании в iOS 7:

Использовать -boundingRectWithSize: options: attributes: context:

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

Ответ 1

Методы

sizeWithFont устарели в iOS7. Вместо этого следует использовать boundingRectWithSize. Если вам также необходимо поддерживать предыдущие версии iOS, вы можете использовать следующий код:

CGSize size = CGSizeZero;

if ([label.text respondsToSelector: @selector(boundingRectWithSize:options:attributes:context:)] == YES) {
    size = [label.text boundingRectWithSize: constrainedSize options: NSStringDrawingUsesLineFragmentOrigin
                                 attributes: @{ NSFontAttributeName: label.font } context: nil].size;
} else {
    size = [label.text sizeWithFont: label.font constrainedToSize: constrainedSize lineBreakMode: UILineBreakModeWordWrap];
}

Ответ 2

Если вы поддерживаете только ios6 и позже, вы можете преобразовать NSStrings в NSAttributedStrings и использовать NSAttributedString boundingRectWithSize:options:context:.

Что-то вроде этого раньше:

CGSize size = [text sizeWithFont:font
               constrainedToSize:(CGSize){maxWidth, CGFLOAT_MAX}];

Может быть легко преобразовано в это и работать как в ios6, так и в ios7:

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

В качестве побочного примечания преимущество этого в том, что ваш размер текста в ios6 теперь является потокобезопасным. Старые методы sizeWithFont:... относятся к UIStringDrawing, что может привести к сбою, если вы одновременно запускаете sizeWithFont:... на двух потоках. В ios6 были открыты новые функции NSStringDrawing для NSAttributedStrings, а функция boundingRectWithSize:... является потокобезопасной. Я предполагаю, что именно поэтому в ios7 старые функции sizeWithFont:... устарели.

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

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

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

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

Ответ 3

sizeWithFont API, который вы используете, устарел на iOS7.

// See UIStringDrawing.h
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode NS_DEPRECATED_IOS(2_0, 7_0, "Use -boundingRectWithSize:options:attributes:context:"); // NSTextAlignment is not needed to determine size

Вы можете использовать предложение API так:

NSMutableDictionary *atts = [[NSMutableDictionary alloc] init];
[atts setObject:myFont forKey:NSFontAttributeName];

CGRect rect = [myText boundingRectWithSize:constraint
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:atts
                                 context:nil];