替换sizeWithFont:ForWidth:lineBreakMode:

Dea*_*ids 5 deprecated nsstring ios7

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

boundingRectWithSize:options:attributes:
Run Code Online (Sandbox Code Playgroud)

这很好,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;
Run Code Online (Sandbox Code Playgroud)

如果我不知道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
Run Code Online (Sandbox Code Playgroud)

Mr.*_*. T 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}];
Run Code Online (Sandbox Code Playgroud)

可以很容易地替换为:

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;
Run Code Online (Sandbox Code Playgroud)

请注意文档提到:

在iOS 7及更高版本中,此方法返回小数大小(在返回的CGRect的大小组件中); 要使用返回的大小来调整视图大小,必须使用ceil函数将其值提升到最接近的更高整数.

因此,要拉出用于调整视图大小的计算高度或宽度,我会使用:

CGFloat height = ceilf(size.height);
CGFloat width  = ceilf(size.width);
Run Code Online (Sandbox Code Playgroud)