objective-c 替换已弃用的 sizeWithFont: 在 iOS 7 中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18897896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:00:24  来源:igfitidea点击:

Replacement for deprecated sizeWithFont: in iOS 7?

objective-cdeprecatedios7

提问by James Kuang

In iOS 7, sizeWithFont:is now deprecated. How do I now pass in the UIFont object into the replacement method sizeWithAttributes:?

在 iOS 7 中,sizeWithFont:现在已弃用。我现在如何将 UIFont 对象传递到替换方法中sizeWithAttributes:

回答by James Kuang

Use sizeWithAttributes:instead, which now takes an NSDictionary. Pass in the pair with key UITextAttributeFontand your font object like this:

使用sizeWithAttributes:相反,现在需要的NSDictionaryUITextAttributeFont像这样传递带有键和字体对象的配对:

CGSize size = [string sizeWithAttributes:
    @{NSFontAttributeName: [UIFont systemFontOfSize:17.0f]}];

// Values are fractional -- you should take the ceilf to get equivalent values
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));

回答by Mr. T

I believe the function was deprecated because that series of NSString+UIKitfunctions (sizewithFont:..., etc) were based on the UIStringDrawinglibrary, which wasn't thread safe. If you tried to run them not on the main thread (like any other UIKitfunctionality), you'll get unpredictable behaviors. In particular, if you ran the function on multiple threads simultaneously, it'll probably crash your app. This is why in iOS 6, they introduced a the boundingRectWithSize:...method for NSAttributedString. This was built on top of the NSStringDrawinglibraries and is thread safe.

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

If you look at the new NSStringboundingRectWithSize:...function, it asks for an attributes array in the same manner as a NSAttributeString. If I had to guess, this new NSStringfunction in iOS 7 is merely a wrapper for the NSAttributeStringfunction from iOS 6.

如果您查看新NSStringboundingRectWithSize:...函数,它会以与 a 相同的方式请求属性数组NSAttributeString。如果非要我猜的话,NSStringiOS 7 中的这个新函数只是对NSAttributeStringiOS 6 函数的封装。

On that note, if you were only supporting iOS 6 and iOS 7, then I would definitely change all of your NSStringsizeWithFont:...to the NSAttributeStringboundingRectWithSize. It'll save you a lot of headache if you happen to have a weird multi-threading corner case! Here's how I converted NSStringsizeWithFont:constrainedToSize::

关于这一点,如果您只支持 iOS 6 和 iOS 7,那么我肯定会将您的所有内容更改NSStringsizeWithFont:...NSAttributeStringboundingRectWithSize. 如果您碰巧有一个奇怪的多线程角落案例,它将为您省去很多麻烦!这是我转换的方式NSStringsizeWithFont:constrainedToSize:

What used to be:

曾经是什么:

NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
CGSize size = [text sizeWithFont:font 
               constrainedToSize:(CGSize){width, CGFLOAT_MAX}];

Can be replaced with:

可以替换为:

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;

Please note the documentation mentions:

请注意文档中提到:

In iOS 7 and later, this method returns fractional sizes (in the size component of the returned CGRect); to use a returned size to size views, you must use raise its value to the nearest higher integer using the ceil function.

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

So to pull out the calculated height or width to be used for sizing views, I would use:

因此,要提取用于调整视图大小的计算高度或宽度,我将使用:

CGFloat height = ceilf(size.height);
CGFloat width  = ceilf(size.width);

回答by Ayush

As you can see sizeWithFontat Apple Developer site it is deprecated so we need to use sizeWithAttributes.

正如您sizeWithFont在 Apple Developer 网站上看到的那样,它已被弃用,因此我们需要使用sizeWithAttributes.

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

NSString *text = @"Hello iOS 7.0";
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
    // code here for iOS 5.0,6.0 and so on
    CGSize fontSize = [text sizeWithFont:[UIFont fontWithName:@"Helvetica" 
                                                         size:12]];
} else {
    // code here for iOS 7.0
   CGSize fontSize = [text sizeWithAttributes: 
                            @{NSFontAttributeName: 
                              [UIFont fontWithName:@"Helvetica" size:12]}];
}

回答by Rom.

I created a category to handle this problem, here it is :

我创建了一个类别来处理这个问题,这里是:

#import "NSString+StringSizeWithFont.h"

@implementation NSString (StringSizeWithFont)

- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
    if ([self respondsToSelector:@selector(sizeWithAttributes:)])
    {
        NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
        return ([self sizeWithAttributes:attribs]);
    }
    return ([self sizeWithFont:fontToUse]);
}

This way you only have to find/replace sizeWithFont:with sizeWithMyFont:and you're good to go.

这样,您只需要查找/替换sizeWithFont:sizeWithMyFont:,你是好去。

回答by user3055587

In iOS7 I needed the logic to return the correct height for the tableview:heightForRowAtIndexPath method, but the sizeWithAttributes always returns the same height regardless of the string length because it doesn't know that it is going to be put in a fixed width table cell. I found this works great for me and calculates the correct height taking in consideration the width for the table cell! This is based on Mr. T's answer above.

在 iOS7 中,我需要逻辑来为 tableview:heightForRowAtIndexPath 方法返回正确的高度,但无论字符串长度如何,sizeWithAttributes 始终返回相同的高度,因为它不知道它将被放入固定宽度的表格单元格中. 我发现这对我很有用,并在考虑表格单元格的宽度的情况下计算正确的高度!这是基于上面T先生的回答。

NSString *text = @"The text that I want to wrap in a table cell."

CGFloat width = tableView.frame.size.width - 15 - 30 - 15;  //tableView width - left border width - accessory indicator - right border width
UIFont *font = [UIFont systemFontOfSize:17];
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;
size.height = ceilf(size.height);
size.width  = ceilf(size.width);
return size.height + 15;  //Add a little more padding for big thumbs and the detailText label

回答by bitsand

Multi-line labels using dynamic height may require additional information to set the size properly. You can use sizeWithAttributes with UIFont and NSParagraphStyle to specify both the font and the line-break mode.

使用动态高度的多行标签可能需要额外的信息来正确设置大小。您可以将 sizeWithAttributes 与 UIFont 和 NSParagraphStyle 一起使用来指定字体和换行模式。

You would define the Paragraph Style and use an NSDictionary like this:

您将定义段落样式并使用这样的 NSDictionary:

// set paragraph style
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
// make dictionary of attributes with paragraph style
NSDictionary *sizeAttributes        = @{NSFontAttributeName:myLabel.font, NSParagraphStyleAttributeName: style};
// get the CGSize
CGSize adjustedSize = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);

// alternatively you can also get a CGRect to determine height
CGRect rect = [myLabel.text boundingRectWithSize:adjustedSize
                                                         options:NSStringDrawingUsesLineFragmentOrigin
                                                      attributes:sizeAttributes
                                                         context:nil];

You can use the CGSize 'adjustedSize' or CGRect as rect.size.height property if you're looking for the height.

如果您正在寻找高度,您可以使用 CGSize 'adjustedSize' 或 CGRect 作为 rect.size.height 属性。

More info on NSParagraphStyle here: https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSParagraphStyle_Class/Reference/Reference.html

有关 NSParagraphStyle 的更多信息,请访问:https: //developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSParagraphStyle_Class/Reference/Reference.html

回答by Kirit Vaghela

// max size constraint
CGSize maximumLabelSize = CGSizeMake(184, FLT_MAX)

// font
UIFont *font = [UIFont fontWithName:TRADE_GOTHIC_REGULAR size:20.0f];

// set paragraph style
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;

// dictionary of attributes
NSDictionary *attributes = @{NSFontAttributeName:font,
                             NSParagraphStyleAttributeName: paragraphStyle.copy};

CGRect textRect = [string boundingRectWithSize: maximumLabelSize
                                     options:NSStringDrawingUsesLineFragmentOrigin
                                  attributes:attributes
                                     context:nil];

CGSize expectedLabelSize = CGSizeMake(ceil(textRect.size.width), ceil(textRect.size.height));

回答by Chris Prince

Building on @bitsand, this is a new method I just added to my NSString+Extras category:

建立在@bitsand 之上,这是我刚刚添加到我的 NSString+Extras 类别中的一个新方法:

- (CGRect) boundingRectWithFont:(UIFont *) font constrainedToSize:(CGSize) constraintSize lineBreakMode:(NSLineBreakMode) lineBreakMode;
{
    // set paragraph style
    NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    [style setLineBreakMode:lineBreakMode];

    // make dictionary of attributes with paragraph style
    NSDictionary *sizeAttributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName: style};

    CGRect frame = [self boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:sizeAttributes context:nil];

    /*
    // OLD
    CGSize stringSize = [self sizeWithFont:font
                              constrainedToSize:constraintSize
                                  lineBreakMode:lineBreakMode];
    // OLD
    */

    return frame;
}

I just use the size of the resulting frame.

我只使用结果帧的大小。

回答by Muhammad Idris

Create a function that takes a UILabel instance. and returns CGSize

创建一个接受 UILabel 实例的函数。并返回 CGSize

CGSize constraint = CGSizeMake(label.frame.size.width , 2000.0);
// Adjust according to requirement

CGSize size;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0){

    NSRange range = NSMakeRange(0, [label.attributedText length]);

    NSDictionary *attributes = [label.attributedText attributesAtIndex:0 effectiveRange:&range];
    CGSize boundingBox = [label.text boundingRectWithSize:constraint options: NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;

    size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
}
else{
    size = [label.text sizeWithFont:label.font constrainedToSize:constraint lineBreakMode:label.lineBreakMode];
}

return size;

回答by DareDevil

Alternate solution-

替代解决方案-

CGSize expectedLabelSize;
if ([subTitle respondsToSelector:@selector(sizeWithAttributes:)])
{
    expectedLabelSize = [subTitle sizeWithAttributes:@{NSFontAttributeName:subTitleLabel.font}];
}else{
    expectedLabelSize = [subTitle sizeWithFont:subTitleLabel.font constrainedToSize:subTitleLabel.frame.size lineBreakMode:NSLineBreakByWordWrapping];
}