似乎无法为UILabel计算NSAttributedString的正确行高

时间:2014-04-07 15:19:48

标签: ios ios7 nsattributedstring

我在阅读this article from objc.io后,使用NSAttributedString's boundingRectWithSize:options:context:方法计算某些文字的预期高度

+(CGSize)postLabelSizeForPost:(ANKPost *)post
{
  CGFloat labelWidth = 220.0f;
  NSAttributedString *text = [BXTPostCell mutableAttributedStringForPost:post];
  NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading;
  CGRect boundingRect = [text boundingRectWithSize:CGSizeMake(labelWidth, CGFLOAT_MAX)
                                         options:options
                                         context:nil];
  CGFloat height = (CGFloat) (ceil(boundingRect.size.height));

  return CGSizeMake(labelWidth, height);
}

然而,当我使用这种方法时,文本实际上并不适合这个大小 - 大小一直太短。

起初,我认为这个问题出现在表情符号中 - 但是应用程序中的许多tableviewcells似乎都在发生。

更新 我和几个人聊过,听起来这个问题可能是boundingRectWithSize:options:context:的潜在错误。我想出了一个解决方法:创建一个虚拟UILabel,为它提供与tableview单元格中UILabel相同的属性(numberOfLines等),然后使用sizeThatFits:来计算尺寸。它确实是一个黑客攻击 - 但它足以解决我的问题。不过我希望它更优雅!

2 个答案:

答案 0 :(得分:3)

在尝试计算UITextView的属性文本大小时,我遇到了同样的效果。我遇到了this answer to another question

诀窍是使用NSLayoutManager's usedRectForTextContainer:。什么是整洁的是这个方法不需要与UITextView一起使用。这意味着您可以将它从mainThread,key用于预先计算UITableViewCell高度。

以下是我如何使用它:

- (CGSize)rectForAttributedString:(NSAttributedString *)string withSize:(CGSize)theSize
{
    if (!string || CGSizeEqualToSize(theSize, CGSizeZero)) {
        return CGSizeZero;
    }

    // setup TextKit stack
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:theSize];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:string];
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

    // query for size
    CGRect rect = [layoutManager usedRectForTextContainer:textContainer];

    return CGSizeMake(ceilf(rect.size.width), ceilf(rect.size.height));
}

为了方便起见,我创建了一种方便的方法来计算特定宽度的高度:

- (CGFloat)textViewHeightForAttributedString:(NSAttributedString *)string withWidth:(CGFloat)width
{
    return [self rectForAttributedString:string withSize:CGSizeMake(width, CGFLOAT_MAX)].height;
}

希望这有帮助。


PS。我对这整个编程工作都很陌生,所以如果我的代码可以优化,请告诉我。

答案 1 :(得分:1)

我想,你可能不会设置preferredMaxLayoutWidth

此属性将约束设置为视图的最大宽度。