在iOS 7中,sizeWithFont:
现已弃用。我现在如何将UIFont对象传递给替换方法sizeWithAttributes:
?
答案 0 :(得分:517)
改为使用sizeWithAttributes:
,现在需要NSDictionary
。使用密钥UITextAttributeFont
和您的字体对象传递一对:
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));
答案 1 :(得分:172)
我认为该函数已被弃用,因为该系列NSString+UIKit
函数(sizewithFont:...
等)基于UIStringDrawing
库,这不是线程安全的。如果您尝试不在主线程上运行它们(与任何其他UIKit
功能一样),您将获得不可预测的行为。特别是,如果您同时在多个线程上运行该函数,它可能会使您的应用程序崩溃。这就是为什么在iOS 6中,他们为boundingRectWithSize:...
引入了NSAttributedString
方法。它建立在NSStringDrawing
库之上,并且是线程安全的。
如果查看新的NSString
boundingRectWithSize:...
函数,它会以与NSAttributeString
相同的方式请求属性数组。如果我不得不猜测,iOS 7中的这个新NSString
函数只是iOS 6中NSAttributeString
函数的包装器。
就此而言,如果您只支持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);
答案 2 :(得分:29)
正如您在Apple Developer网站上看到sizeWithFont
一样,我们不推荐使用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]}];
}
答案 3 :(得分:16)
我创建了一个类别来处理这个问题,这里是:
#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]);
}
这样您只需要sizeWithFont:
查找/替换sizeWithMyFont:
,就可以了。
答案 4 :(得分:10)
在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
答案 5 :(得分:7)
使用动态高度的多行标签可能需要其他信息才能正确设置大小。您可以将sizeWithAttributes与UIFont和NSParagraphStyle一起使用来指定字体和换行模式。
您将定义段落样式并使用如下的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];
您可以使用CGSize' adjustSize'或者,如果您正在寻找高度,则将CGRect设置为rect.size.height属性。
有关NSParagraphStyle的更多信息:https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSParagraphStyle_Class/Reference/Reference.html
答案 6 :(得分:4)
// 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));
答案 7 :(得分:3)
创建一个带有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;
答案 8 :(得分:3)
替代解决方案 -
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];
}
答案 9 :(得分:3)
在@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;
}
我只使用结果帧的大小。
答案 10 :(得分:2)
您仍然可以使用sizeWithFont
。但是,在iOS> = 7.0中,如果字符串包含前导空格或尾随空格或结束行\n
,则会导致崩溃。
在使用前修剪文字
label.text = [label.text stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
这也适用于sizeWithAttributes
和[label sizeToFit]
。
此外,只要您在iOS 7.0设备中拥有nsstringdrawingtextstorage message sent to deallocated instance
,它就会处理此问题。
答案 11 :(得分:2)
更好地使用自动尺寸(Swift):
tableView.estimatedRowHeight = 68.0
tableView.rowHeight = UITableViewAutomaticDimension
NB: 1.应该正确设计UITableViewCell原型(例如,不要忘记设置UILabel.numberOfLines = 0等) 2.删除HeightForRowAtIndexPath方法
VIDEO: https://youtu.be/Sz3XfCsSb6k
答案 12 :(得分:1)
boundingRectWithSize:options:attributes:context:
答案 13 :(得分:1)
Accepted answer将是(使用sizeWithAttributes和UITextAttributeFont):
UIStringAttributes attributes = new UIStringAttributes
{
Font = UIFont.SystemFontOfSize(17)
};
var size = text.GetSizeUsingAttributes(attributes);
答案 14 :(得分:0)
如果有人需要,这是单调的等价物:
/// <summary>
/// Measures the height of the string for the given width.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="width">The width.</param>
/// <param name="padding">The padding.</param>
/// <returns></returns>
public static float MeasureStringHeightForWidth(this string text, UIFont font, float width, float padding = 20)
{
NSAttributedString attributedString = new NSAttributedString(text, new UIStringAttributes() { Font = font });
RectangleF rect = attributedString.GetBoundingRect(new SizeF(width, float.MaxValue), NSStringDrawingOptions.UsesLineFragmentOrigin, null);
return rect.Height + padding;
}
可以这样使用:
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
//Elements is a string array
return Elements[indexPath.Row].MeasureStringHeightForWidth(UIFont.SystemFontOfSize(UIFont.LabelFontSize), tableView.Frame.Size.Width - 15 - 30 - 15);
}
答案 15 :(得分:0)
CGSize maximumLabelSize = CGSizeMake(label.frame.size.width, FLT_MAX);
CGSize expectedLabelSize = [label sizeThatFits:maximumLabelSize];
float heightUse = expectedLabelSize.height;
答案 16 :(得分:0)
试试这个语法:
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:@{NSFontAttributeName: font}];
答案 17 :(得分:0)
- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
if ([self respondsToSelector:@selector(sizeWithAttributes:)])
{
NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
return ([self sizeWithAttributes:attribs]);
}
return ([self sizeWithFont:fontToUse]);
}
答案 18 :(得分:0)
作为@Ayush答案:
在Apple Developer网站上您可以看到
sizeWithFont
,因此已弃用,因此我们需要使用sizeWithAttributes
。
好吧,假设在2019年以后,您可能正在使用 Swift 和def addBinary(self, a: str, b: str) -> str:
carry = 0
result = ''
a = list(a)
b = list(b)
while a or b or carry:
if a:
carry += int(a.pop())
if b:
carry += int(b.pop())
result += str(carry %2)
carry //= 2
return result[::-1]
而不是Objective-c和String
,这是获取a大小的正确方法NSString
,带有预定义的字体:
String
答案 19 :(得分:-1)
在ios 7中,这些都不适合我。这就是我最终要做的事情。我把它放在我的自定义单元类中,并在我的heightForCellAtIndexPath方法中调用该方法。
在应用商店中查看应用时,我的单元格与描述单元格类似。
首先在故事板中,将标签设置为'attributedText',将行数设置为0(将自动调整标签大小(仅限ios 6+))并将其设置为自动换行。
然后我只是在我的自定义Cell Class中添加单元格内容的所有高度。在我的情况下,我在顶部有一个标签,总是说“描述”(_descriptionHeadingLabel),一个较小的标签,其大小可变,包含从单元格顶部到标题的约束的实际描述(_descriptionLabel)(_descriptionHeadingLabelTopConstraint) 。我还在底部添加了3个空格(大约相同数量的苹果放在字幕类型单元格上。)
- (CGFloat)calculateHeight
{
CGFloat width = _descriptionLabel.frame.size.width;
NSAttributedString *attributedText = _descriptionLabel.attributedText;
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX} options: NSStringDrawingUsesLineFragmentOrigin context:nil];
return rect.size.height + _descriptionHeadingLabel.frame.size.height + _descriptionHeadingLabelTopConstraint.constant + 3;
}
在我的表格视图委托中:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
if (indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"descriptionCell"];
DescriptionCell *descriptionCell = (DescriptionCell *)cell;
NSString *text = [_event objectForKey:@"description"];
descriptionCell.descriptionLabel.text = text;
return [descriptionCell calculateHeight];
}
return 44.0f;
}
您可以将if语句更改为“更聪明”并实际从某种数据源获取单元格标识符。在我的情况下,单元格将被硬编码,因为它们将按特定顺序固定数量。