Как рассчитать высоту NSAttributedString, заданную ширину и количество строк?

Я хочу отобразить 3 строки NSAttributedString. Есть ли способ определить нужную высоту по ширине и количеству строк?

И я не хочу создавать UILabel для вычисления размера, так как я хочу, чтобы вычисление выполнялось в фоновом потоке.

Ответ 1

Интересно, почему это все еще остается без ответа. Во всяком случае, здесь самый быстрый метод, который работает для меня.

Создайте категорию NSAttributedString под названием "Высота". Это должно сгенерировать два файла под названием "NSAttributedString + Height. {H, m}"

В файле .h:

@interface NSAttributedString (Height)  
-(CGFloat)heightForWidth:(CGFloat)width;  
@end  

В файле .m:

-(CGFloat)heightForWidth:(CGFloat)width  
{  
    return ceilf(CGRectGetHeight([self boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
                                                    options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
                                                    context:nil])) + 1;  
}

Вот что происходит:

  • boundRectWithSize: options: context get rect, ограниченный шириной, которую вы передаете методу. Опция NSStringDrawingUsesLineFragmentOrigin указывает, что она ожидает многострочную строку.
  • Затем мы выбираем параметр height из этого прямоугольника.
  • В iOS 7 этот метод возвращает десятичные числа. Нам нужна круглая фигура. ceilf помогает с этим.
  • Мы добавляем дополнительную единицу к возвращаемому значению.

Здесь, как его использовать

NSAttributedString *string = ...
CGFloat height = [string heightForWidth:320.0f];

Вы можете использовать эту высоту для вычислений компоновки.

Ответ 2

Ответ от @dezinezync отвечает на половину вопроса. Вам просто нужно вычислить максимальный размер, разрешенный для вашего UILabel с заданной шириной и количеством строк.

Сначала установите разрешенную высоту в зависимости от количества строк:

let maxHeight = font.lineHeight * numberOfLines

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

let labelStringSize = yourText.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), maxHeight),
            options: NSStringDrawingOptions.UsesLineFragmentOrigin,
            attributes: [NSFontAttributeName: font],
            context: nil).size

Ответ 3

Это обходное решение, и я думаю, что есть лучший способ...

static UILabel *label;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    label = [UILabel new];
});
label.attributedText = givenAttributedString;
CGRect rect = CGRectMake(0,0,givenWidth,CGFLOAT_MAX)
CGFloat height = [label textRectForBounds:rect
                        limitedToNumberOfLines:2].size.height;