iOS 7中废弃的-sizeWithFont:constrainedToSize:lineBreakMode:,有什么替代方法?

147

iOS 7 中,该方法:

- (CGSize)sizeWithFont:(UIFont *)font
     constrainedToSize:(CGSize)size
         lineBreakMode:(NSLineBreakMode)lineBreakMode 

以及方法:

- (CGSize)sizeWithFont:(UIFont *)font

已不推荐使用。如何替换?

CGSize size = [string sizeWithFont:font
                 constrainedToSize:constrainSize
                     lineBreakMode:NSLineBreakByWordWrapping];

和:

CGSize size = [string sizeWithFont:font];

2
替代方法是 -sizeWithAttributes: - holex
好的,Holex,谢谢。但是,我该如何使用标签中的字体,例如NSDIctionary?如果我的代码像这样:sizeWithFont:customlabel.font; 那么void会询问“sizeWithAttributes:<#(NSDictionary *)#>”。 - user_Dennis_Mostajo
1
这是如何定义属性的官方文档链接:https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSAttributedString_UIKit_Additions/Reference/Reference.html#//apple_ref/doc/uid/TP40011688 - holex
8个回答

222

你可以尝试这个:

CGRect textRect = [text boundingRectWithSize:size
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName:FONT}
                                 context:nil];

CGSize size = textRect.size;

只需将 "FONT" 更改为 "[UIFont font....]"


13
你在哪里提到了NSLineBreakByWordWrapping?它去哪了? - user4951
32
NSLineBreakByWordWrapping需要放在NSParagraphStyle中。例如:NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; 然后在属性中需要添加 NSParagraphStyleAttributeName: paragraphStyle.copy... - Florian Friedrich
1
在我的情况下,除了 NSLineBreakByWordWrapping 之外添加带有换行符的 paragraphStyle 导致计算大小仅针对一行... 有什么想法吗? - manicaesar
9
请不要忘记 boundingRectWithSize:options:attributes:context: 返回的值是小数。你需要分别使用 ceil(textRect.size.height)ceil(textRect.size.width) 来获取实际的高度和宽度。 - Florian Friedrich
20
BOLIVIASize是什么意思? - JRam13
显示剩余7条评论

36

由于 sizeWithAttributes 在 iOS 4.3 以上的版本中不能使用,因此我们必须为 iOS 7.0 及其以下版本编写条件代码。

1)解决方案1:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
   CGSize size = CGSizeMake(230,9999);
   CGRect textRect = [specialityObj.name  
       boundingRectWithSize:size
                    options:NSStringDrawingUsesLineFragmentOrigin
                 attributes:@{NSFontAttributeName:[UIFont fontWithName:[AppHandlers zHandler].fontName size:14]}
                    context:nil];
   total_height = total_height + textRect.size.height;   
}
else {
   CGSize maximumLabelSize = CGSizeMake(230,9999); 
   expectedLabelSize = [specialityObj.name sizeWithFont:[UIFont fontWithName:[AppHandlers zHandler].fontName size:14] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap]; //iOS 6 and previous. 
   total_height = total_height + expectedLabelSize.height;
}

2) 解决方案2

UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16]; // Your Font-style whatever you want to use.
gettingSizeLabel.text = @"YOUR TEXT HERE";
gettingSizeLabel.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(310, 9999); // this width will be as per your requirement

CGSize expectedSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

第一种解决方案有时无法返回正确的高度值,因此请使用另一种完美运行的解决方案。

第二个选项在所有iOS上都能很好地工作,并且没有条件代码。


1
为什么是230和999?你从哪里得到这个数字的? - user4951
1
230 可以是任何数字。它代表您想要的标签宽度。我更愿意用无穷大或MAXFLOAT替换9999。 - Florian Friedrich
第二个解决方案非常有效。谢谢Nirav。 - Jim
1
"[AppHandlers zHandler]" 出现错误,提示“未声明的标识符”。如何解决? - Dimple

9

以下是简单的解决方案:

要求:

CGSize maximumSize = CGSizeMake(widthHere, MAXFLOAT);
UIFont *font = [UIFont systemFontOfSize:sizeHere];

现在在 iOS 7.0 中,constrainedToSizeusage:lineBreakMode: 的用法已经被弃用:

CGSize expectedSize = [stringHere sizeWithFont:font constrainedToSize:maximumSize lineBreakMode:NSLineBreakByWordWrapping];

现在,在 iOS 7.0 的更高版本中使用方式如下:

// Let's make an NSAttributedString first
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:stringHere];
//Add LineBreakMode
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
[attributedString setAttributes:@{NSParagraphStyleAttributeName:paragraphStyle} range:NSMakeRange(0, attributedString.length)];
// Add Font
[attributedString setAttributes:@{NSFontAttributeName:font} range:NSMakeRange(0, attributedString.length)];

//Now let's make the Bounding Rect
CGSize expectedSize = [attributedString boundingRectWithSize:maximumSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;

7
以下是两种简单的方法,可替换这两种已弃用的方法。
以下是相关参考文献:
如果您正在使用NSLineBreakByWordWrapping,则不需要指定NSParagraphStyle,因为它是默认值: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSParagraphStyle_Class/index.html#//apple_ref/occ/clm/NSParagraphStyle/defaultParagraphStyle 必须获取大小的ceil,以匹配弃用的方法的结果。 https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSString_UIKit_Additions/#//apple_ref/occ/instm/NSString/boundingRectWithSize:options:attributes:context:
+ (CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font {    
    CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: font}];
    return CGSizeMake(ceilf(size.width), ceilf(size.height));
}

+ (CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
    CGRect textRect = [text boundingRectWithSize:size
                                     options:NSStringDrawingUsesLineFragmentOrigin
                                  attributes:@{NSFontAttributeName: font}
                                     context:nil];
    return CGSizeMake(ceilf(textRect.size.width), ceilf(textRect.size.height));
}

6

在大多数情况下,我使用方法sizeWithFont:constrainedToSize:lineBreakMode:来估计一个UILabel的最小尺寸,以适应其文本内容(特别是当标签需要放置在UITableViewCell中时)...

...如果这恰好是您所处的情况,您可以简单地使用以下方法:

CGSize size = [myLabel textRectForBounds:myLabel.frame limitedToNumberOfLines:mylabel.numberOfLines].size;

希望这能有所帮助。

5
苹果的文档说明,您不应直接调用此方法。 - Barlow Tucker
至少在iOS 7 SDK文档中没有提到。 - Rivera

3
UIFont *font = [UIFont boldSystemFontOfSize:16];
CGRect new = [string boundingRectWithSize:CGSizeMake(200, 300) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: font} context:nil];
CGSize stringSize= new.size;

3
欢迎来到StackOverFlow。请勿再次发布相同的答案。如果您需要为答案添加内容,请发表评论或对答案进行编辑。 - Ramaraj T
好的,我会在下次考虑到这个。谢谢你的建议。 - user3575114

2

[被接受的答案在一个类别中运行得很好。我正在覆盖已弃用的方法名称。这是个好主意吗?在Xcode 6.x中似乎没有任何投诉]

如果您的部署目标是7.0或更高版本,则此方法有效。类别为NSString(Util)

NSString + Util.h

- (CGSize)sizeWithFont:(UIFont *) font;
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size;

NSString+Util.m

- (CGSize)sizeWithFont:(UIFont *) font {
    NSDictionary *fontAsAttributes = @{NSFontAttributeName:font};
    return [self sizeWithAttributes:fontAsAttributes];
}

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size {
    NSDictionary *fontAsAttributes = @{NSFontAttributeName:font};
    CGRect retVal = [self boundingRectWithSize:size
                                     options:NSStringDrawingUsesLineFragmentOrigin
                                  attributes:fontAsAttributes context:nil];
    return retVal.size;
}

1
UIFont *font = [UIFont fontWithName:@"Courier" size:16.0f];

NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentRight;

NSDictionary *attributes = @{ NSFontAttributeName: font,
                    NSParagraphStyleAttributeName: paragraphStyle };

CGRect textRect = [text boundingRectWithSize:size
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:attributes
                                 context:nil];

CGSize size = textRect.size;

从两个答案 1 + 2 中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接