CoreText归因字符串高度计算不准确

时间:2014-05-25 04:02:04

标签: ios objective-c uicollectionview core-text

CoreText没有给出属性字符串的正确高度(它的短或一行或更多)。我已经看到很多关于此的帖子,但无法理解或找到解决方案。有人可以解释Core Text高度计算的工作原理吗?这是我写的一个示例代码,显示了不准确的高度计算。

上下文

我有一个集合视图,其中单元格的高度由其中的内容决定。 我在单元格中显示文本段落。我想通过使用核心文本进行高度计算来保存一些性能。我已经看到,使用核心文本的高度计算,我可以节省约300毫秒。

代码

//高度计算

+ (CGFloat)getHeight
{
    NSString *text = @"The Apple HIG recommends to use a common color for links and buttons and we did just that. By using the same color throughout the app we trained the user to always associate blue to a link.The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.";

    NSAttributedString *attrStr = [self attributedString:text withLinespacing:3 withLineBreakMode:NSLineBreakByWordWrapping];

    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attrStr));
    CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(frameSetter,
                                                                    CFRangeMake(0, attrStr.length),
                                                                    NULL,
                                                                    CGSizeMake(320, 9999),
                                                                    NULL);

    return suggestedSize.height;
}

//当Cell即将显示时加载相同的文本

- (void)loadData
{
    NSString *text = @"The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.The Apple HIG recommends to use a common color for links and buttons and we did just that.By using the same color throughout the app we trained the user to always associate blue to a link.";

    NSAttributedString *attrStr = [[self class] attributedString:text withLinespacing:3 withLineBreakMode:NSLineBreakByWordWrapping];

    // UILabel element
    self.textLabel.attributedText = attrStr;

    self.layer.borderColor = [UIColor blueColor].CGColor;
    self.layer.borderWidth = 1.0f;
}

//使用leading,font和linebreak生成属性字符串

+ (NSAttributedString *)attributedString:(NSString *)string
                        withLinespacing:(CGFloat)linespacing
                      withLineBreakMode:(NSLineBreakMode)lineBreakMode
{
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:string];
    NSInteger strLength = [string length];
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    style.lineSpacing = linespacing;
    style.lineBreakMode = lineBreakMode;

    [attrStr addAttributes:@{NSParagraphStyleAttributeName: style,
                         NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue" size:15]} range:NSMakeRange(0, strLength)];

    return attrStr;
}

上面的代码使用核心文本来计算高度,使用UILabel来显示文本。 UILabel对细胞有3个限制 {Top:17,Leading:13px,Trailing:13px}

enter image description here

1 个答案:

答案 0 :(得分:4)

众所周知,

CTFramesetterSuggestFrameSizeWithConstraints是错误的,返回不正确的身高值。您遇到的缺失线错误是非常常见的,并且我知道没有好的解决方案,只有丑陋的解决方法从未给出100%准确的结果。

对于iOS7及更高版本,我建议您转到TextKit。不知何故,内部执行的计算也能正常工作,同时也基于Core Text。使用NSLayoutManager的{​​{1}}会返回正确的结果。

您可以看到更完整的答案here。虽然不是100%主题,但有一些关于核心文本计算的冗余的讨论。