替换sizeWithFont:ForWidth:lineBreakMode:

时间:2013-09-23 00:28:42

标签: nsstring ios7 deprecated

我在iOS7中已弃用了许多用于确定用于创建复杂pdf文档的打印字符串布局的方法。文档调用相同的方法来替换所有不推荐使用的sizeWithFont方法:

boundingRectWithSize:options:attributes:

这对于sizeWithFont:ConstrainedTosize:lineBreakMode来说没什么问题,但如果我只想让我的字符串在一行上呢?我不知道如何使用最大高度,所以我没有一个矩形作为第一个参数的值移交。

这是我限制到给定大小时所拥有的。

CGFloat maxHeightAllowable = _maxHeight;
CGSize issueTitleMaxSize = CGSizeMake(_issueListTitleColWidth - (kColumnMargin *2), maxHeightAllowable);
NSDictionary *issueTitleAttributes = [NSDictionary dictionaryWithObjectsAndKeys:_bodyFont, NSFontAttributeName, nil];
CGRect issueTitleRect = CGRectIntegral([issueTitleText boundingRectWithSize:issueTitleMaxSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:issueTitleAttributes context:nil]);
CGSize issueTitleSize = issueTitleRect.size;

如果我不知道maxHeight,或者实际上,一行的高度正是我想要找到的,我将如何使用相同的方法?

我明白为什么他们正在推动NSAttributed字符串和自动布局的兼容性,但为什么要弃用这些呢?在我的情况下,替换现在需要4或5个步骤,过去曾经是1或2。

根据T先生的建议,使用font的lineHeight属性,我将这些方法放在一个类别中,大大简化了我的替换。

#import "NSString+SizingForPDF.h"

@implementation NSString (SizingForPDF)

-(CGSize)integralSizeWithFont:(UIFont *)font constrainedToSize:(CGSize)maxSize
{
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
    CGRect rect = CGRectIntegral([self boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:attributes context:nil]);
    return rect.size;
}

-(CGSize)integralSizeWithFont:(UIFont *)font maxWidth:(CGFloat)maxWidth numberOfLines:(NSInteger)lines
{
    if (lines == 0) {
        lines = 1;
    }
    NSDictionary *attributes = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
    CGFloat height = font.lineHeight * lines;
    CGSize maxsize = CGSizeMake(maxWidth, height);
    CGRect rect = CGRectIntegral([self boundingRectWithSize:maxsize options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesFontLeading attributes:attributes context:nil]);
    return rect.size;
}

@end

1 个答案:

答案 0 :(得分:15)

如果你只想找到一行的高度,你不能只使用你的字体的lineHeight属性吗?我用它来设置标签的高度或正确预测元素的高度而没有任何问题。我不确定pdf文件在这方面是否有所不同。

此外,我相信这些函数已被弃用,因为NSString + UIKit函数(sizeWithFont:...等)系列基于UIStringDrawing库,它不是线程安全的。如果您尝试不在主线程上运行它们(就像任何其他UIKit功能一样),您将获得不可预测的行为。特别是,如果您同时在多个线程上运行该函数,它可能会使您的应用程序崩溃。这就是为什么在iOS 6中,他们为NSAttributedStrings引入了boundingRectWithSize:...方法。它建立在NSStringDrawing库之上,并且是线程安全的。

就此而言,如果您只支持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);