Objective c 替换iOS 7中不推荐的sizeWithFont:?

Objective c 替换iOS 7中不推荐的sizeWithFont:?,objective-c,deprecated,ios7,Objective C,Deprecated,Ios7,在iOS 7中,sizeWithFont:现在已被弃用。现在如何将UIFont对象传递到替换方法SizeWithatAttributes:?使用SizeWithatAttributes:,它现在需要一个NSDictionary。用keyuitextattributefort和字体对象传递一对,如下所示: public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath) { //Eleme

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

使用
SizeWithatAttributes:
,它现在需要一个
NSDictionary
。用key
uitextattributefort
和字体对象传递一对,如下所示:

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);
}
// 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];
CGRect-rawRect={};
rawRect.size=[字符串大小属性:@{
NSFontAttributeName:[UIFont systemFontOfSize:17.0f],
}];
//值是分数的——您应该使用ceil来获得相等的值
CGSize adjustedSize=CGRectIntegral(rawRect).size;
正如您在Apple开发者网站上看到的,它已被弃用,因此我们需要使用


创建一个接受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;

我认为该函数已被弃用,因为该系列的
NSString+UIKit
函数(
sizewithFont:…
,等等)基于
UIStringDrawing
库,这不是线程安全的。如果您试图不在主线程上运行它们(与任何其他
UIKit
功能一样),您将获得不可预测的行为。特别是,如果同时在多个线程上运行该函数,可能会使应用程序崩溃。这就是为什么在iOS 6中,他们为
NSAttributedString
引入了
boundingRectWithSize:…
方法。这是建立在
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;
可以替换为:

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);

我创建了一个类别来处理此问题,如下所示:

#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:
找到/替换
sizeWithFont:
,就可以了。

替代解决方案-

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];
}

您仍然可以使用
sizeWithFont
。但是,在iOS>=7.0中,如果字符串包含前导空格和尾随空格或结束行,则方法会导致崩溃
\n

使用前修剪文本

label.text = [label.text stringByTrimmingCharactersInSet:
             [NSCharacterSet whitespaceAndNewlineCharacterSet]];
这也可能适用于
sizewithattattributes
[label sizeToFit]


此外,每当您在iOS 7.0设备中将
nsstringdrawingtextstorage消息发送到已解除分配的实例时,它都会处理此问题。

在iOS 7中,这些都不适用于我。这就是我最后要做的。我将其放在自定义单元格类中,并在heightForCellAtIndexPath方法中调用该方法

- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
    if ([self respondsToSelector:@selector(sizeWithAttributes:)])
    {
        NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
        return ([self sizeWithAttributes:attribs]);
    }
    return ([self sizeWithFont:fontToUse]);
}
在应用商店中查看应用时,“我的手机”与“说明”手机类似

首先在故事板中,将标签设置为“attributedText”,将行数设置为0(这将自动调整标签大小(仅限ios 6+),并将其设置为word wrap

然后,我只需将自定义单元格类中单元格内容的所有高度相加。在我的例子中,顶部有一个标签总是写着“Description”(_descriptionHeadingLabel),一个较小的标签,大小可变,包含实际描述(_descriptionLabel)从单元格顶部到标题的约束(_descriptionHeadingLabelTopConstraint)。我还添加了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语句更改为稍微“智能化”,并实际从某种数据源获取单元标识符。在我的例子中,这些单元将被硬编码,因为它们将以特定的顺序固定数量

在iOS7中,我需要逻辑来为tableview:heightForRowAtIndexPath方法返回正确的高度,但是无论字符串长度如何,sizewattributes始终返回相同的高度,因为它不知道它将被放入固定宽度的表单元格中。我发现这对我来说非常有用,并考虑到表格单元格的宽度来计算正确的高度!这是基于上面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
在Xamarin中(使用sizeWithAttributes和UITextAttributeFont):


如果有人需要,这里是monotouch的等价物:

/// <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;
}

更好地使用自动标注(Swift):

注意: 1.UITableViewCell原型应正确设计(例如,不要忘记设置UILabel.numberOfLines=0等) 2.删除RowAtIndexPath方法的高度

视频:

使用动态高度的多行标签可能需要其他信息才能正确设置尺寸。可以将sizeWithAttributes与UIFont和NSParagraphStyle一起使用来指定字体和换行模式

您可以定义段落样式并使用如下NSDictionary:

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);
}
// 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“adjustedSize”或CGRect as rect.size.height属性

有关NSParagraphStyle的更多信息,请点击此处:

在@bitsand上构建
CGSize maximumLabelSize = CGSizeMake(label.frame.size.width, FLT_MAX);
CGSize expectedLabelSize = [label sizeThatFits:maximumLabelSize];
float heightUse = expectedLabelSize.height;
// 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];
- (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;
}
NSAttributedString *attributedText =
    [[NSAttributedString alloc] initWithString:text 
                                    attributes:@{NSFontAttributeName: font}];
// 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));
let stringSize = NSString(string: label.text!).size(withAttributes: [.font : UIFont(name: "OpenSans-Regular", size: 15)!])