5

我用来确定打印字符串布局以创建复杂 pdf 文档的许多方法在 iOS7 中已被弃用。文档调用了相同的方法来替换所有已弃用的 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 个步骤。

使用字体的 lineHeight 属性,正如 T 先生所建议的那样,我将这些方法放在一个类别中,大大简化了我的替换。

#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
4

1 回答 1

15

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

此外,我认为这些函数已被弃用,因为该系列 NSString+UIKit 函数(sizeWithFont:...等)基于 UIStringDrawing 库,它不是线程安全的。如果您尝试不在主线程上运行它们(就像任何其他 UIKit 功能一样),您将获得不可预知的行为。特别是,如果您同时在多个线程上运行该函数,它可能会使您的应用程序崩溃。这就是为什么在 iOS 6 中,他们引入了boundingRectWithSize:...NSAttributedStrings 的方法。这是建立在 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);
于 2013-09-23T03:36:26.340 回答