objective-c 我应该用什么替换已弃用的 sizeWithFont: 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18315441/
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
With what should I replace the deprecated sizeWithFont: method?
提问by Rambatino
I have a method that gives me the perfect size for a UITextView given a length of string (with the corresponding correct font size) :
我有一种方法可以为给定字符串长度(具有相应的正确字体大小)的 UITextView 提供完美的大小:
- (NSInteger) heightOfLabel:(NSString*) string {
CGSize maximumLabelSize = CGSizeMake([[UIScreen mainScreen] bounds].size.width - 40, FLT_MAX);
CGSize expectedLabelSize = [[NSString stringTrimmedForLeadingAndTrailingWhiteSpacesFromString:string]
sizeWithFont:[UIFont systemFontOfSize:15]
constrainedToSize:maximumLabelSize
lineBreakMode:NSLineBreakByWordWrapping];
return expectedLabelSize.height + 5;
}
In fact, it still gives me a perfect fit, even in iOS7. Although now it comes up with a warning method that says I shouldn't use 'sizeWithFont:contrainedToSize:lineBreakMode'.
事实上,它仍然给我一个完美的契合,即使在 iOS7 中也是如此。虽然现在它提出了一个警告方法,说我不应该使用“sizeWithFont:contrainedToSize:lineBreakMode”。
It now says I should be using -boundingRectWithSize:options:attributes:context:
它现在说我应该使用 -boundingRectWithSize:options:attributes:context:
This method isn't new to iOS7 and therefore i figure that it is okay to ask it on stack overflow, rather than going across to the official apple developers forum.
这种方法对 iOS7 来说并不新鲜,因此我认为在堆栈溢出时询问它是可以的,而不是转到官方的苹果开发者论坛。
I have three questions:
我有三个问题:
1) Because it is deprecated, does that mean I should definitely replace it, despite it still working?
1)因为它已被弃用,这是否意味着我肯定应该更换它,尽管它仍然有效?
2) I have tried many different boundingRectWithSize: methods, with various variables but it is never perfect, it always seems to be slightly out (as many stackoverflow questions point out) - is there a perfect replacement with this none-deprecated method that does exactly the same as my previous method with as minimal hassle?
2)我尝试了许多不同的 boundingRectWithSize: 方法,具有各种变量,但它从来都不是完美的,它似乎总是有点出问题(正如许多 stackoverflow 问题所指出的那样)- 是否有一个完美的替代方法可以完全替代这种未弃用的方法和我以前的方法一样,麻烦最少?
3) why remove this method? Is it because of the overlap with this other method?
3)为什么删除这个方法?是因为与其他方法重叠吗?
回答by Rambatino
After an hour of trial error I managed to make it work:
经过一个小时的试错后,我设法让它工作:
CGSize maximumLabelSize = CGSizeMake(tableView.width, MAXFLOAT);
NSStringDrawingOptions options = NSStringDrawingTruncatesLastVisibleLine |
NSStringDrawingUsesLineFragmentOrigin;
NSDictionary *attr = @{NSFontAttributeName: [UIFont systemFontOfSize:15]};
CGRect labelBounds = [string boundingRectWithSize:maximumLabelSize
options:options
attributes:attr
context:nil];
Update:
更新:
As Mr. T mentions in answer below : 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.ceilffunction is recommended to use.
正如 T 先生在下面的回答中提到的:在 iOS 7 及更高版本中,此方法返回小数大小(在返回的 CGRect 的大小组件中);要使用返回的大小来调整视图的大小,您必须使用 ceil 函数将其值提高到最接近的更高整数。ceilf建议使用功能。
CGFloat height = ceilf(labelBounds.size.height);
回答by Mr. T
I believe the function was deprecated because that series of NSString+UIKit functions were based on the UIStringDrawing library, which wasn't thread safe. If you tried to run them not on the main thread (like any other UIKit functionality), 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 NSAttributedStrings. This was built on top of the NSStringDrawing libraries and is thread safe.
我相信该函数已被弃用,因为该系列 NSString+UIKit 函数基于 UIStringDrawing 库,该库不是线程安全的。如果您尝试不在主线程上运行它们(像任何其他 UIKit 功能一样),您将获得不可预测的行为。特别是,如果您同时在多个线程上运行该函数,它可能会使您的应用程序崩溃。这就是为什么在 iOS 6 中,他们boundingRectWithSize:...为 NSAttributedStrings引入了一个方法。这是建立在 NSStringDrawing 库之上的,并且是线程安全的。
If you look at the new NSString boundingRectWithSize:...function, it asks for an attributes array in the same manner as a NSAttributeString. If I had to guess, this new NSString function in iOS 7 is merely a wrapper for the NSAttributeString function from iOS 6.
如果您查看新的 NSStringboundingRectWithSize:...函数,它会以与 NSAttributeString 相同的方式请求属性数组。如果我不得不猜测,iOS 7 中的这个新 NSString 函数只是 iOS 6 中 NSAttributeString 函数的包装器。
On that note, if you were only supporting iOS 6 and iOS 7, then I would definitely change all of your NSString's sizeWithFont:...to the NSAttributeString's boundingRectWithSize. It'll save you a lot of headache if you happen to have a weird multi-threading corner case! Here's how I converted NSString's sizeWithFont:constrainedToSize::
关于这一点,如果您只支持 iOS 6 和 iOS 7,那么我肯定会将您所有的 NSString 更改sizeWithFont:...为 NSAttributeString 的boundingRectWithSize. 如果您碰巧有一个奇怪的多线程角落案例,它将为您省去很多麻烦!这是我转换 NSString 的方法sizeWithFont:constrainedToSize::
What used to be:
曾经是什么:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
CGSize size = [text sizeWithFont:font
constrainedToSize:CGSizeMake(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:CGSizeMake(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 Alexander of Norway
For linebreak issue:
对于换行问题:
- (CGFloat)heightNeededForText:(NSString *)text withFont:(UIFont *)font width:(CGFloat)width lineBreakMode:(NSLineBreakMode)lineBreakMode {
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = lineBreakMode;
CGSize size = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:@{ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle }
context:nil].size;
return ceilf(size.height);
}
回答by Koti Tummala
Swift version of the Alexander of Norway's answer...
挪威亚历山大答案的 Swift 版本......
func heightNeededForText(text: NSString, withFont font: UIFont, width: CGFloat, lineBreakMode:NSLineBreakMode) -> CGFloat {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = lineBreakMode
let size: CGSize = text.boundingRectWithSize(CGSizeMake(width, CGFloat.max), options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: [ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle], context: nil).size//text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MA
return ceil(size.height);
}
In the code where you want to get the height just call the method like below...
在要获取高度的代码中,只需调用如下方法...
let size = self.heightNeededForText(text as NSString, withFont: UIFont.systemFontOfSize(15.0), width: scrollView.frame.size.width - 20, lineBreakMode: NSLineBreakMode.ByWordWrapping) //Can edit the font size and LinebreakMode

