【问题标题】:sizeWithFont method is deprecated. boundingRectWithSize returns an unexpected valuesizeWithFont 方法已弃用。 boundingRectWithSize 返回一个意外的值
【发布时间】:2013-10-24 06:54:05
【问题描述】:

在 iOS7 中,sizeWithFont 已被弃用,所以我使用boundingRectWithSize(它返回一个 CGRect 值)。我的代码:

 UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                    // you can use your font.

 CGSize maximumLabelSize = CGSizeMake(310, 9999);

 CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                             options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{NSFontAttributeName:fontText}
                             context:nil];

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

textRect 中,我得到的尺寸比maximumLabelSize 大,与使用sizeWithFont 时的尺寸不同。我该如何解决这个问题?

【问题讨论】:

  • 我遇到了所有字体的这个问题,不仅是系统字体或 Helvetica。
  • 你知道怎么做吗?
  • 字体名称、文本和大小不匹配的具体示例可能会有所帮助。
  • 我曾经在 iOS6 中使用 CTFramesetterSuggestFrameSizeWithConstraints 来计算属性字符串的高度,它总是返回正确的高度。在 iOS7 中,CTFramesetterSuggestFrameSizeWithConstraints 和 boundingRectWithSize 都给我一个错误的高度结果。我敢打赌这是 iOS7 中引入的一个错误,似乎还没有解决方案。
  • 我也面临同样的问题,最好使用 tttattributedlabel

标签: objective-c nsstring ios7 uilabel


【解决方案1】:

这是我的工作代码 sn-p:

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:attributeDict];

NSString *headline  = [dict objectForKey:@"title"];  
UIFont *font        = [UIFont boldSystemFontOfSize:18];  
CGRect  rect        = [headline boundingRectWithSize:CGSizeMake(300, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];

CGFloat height      = roundf(rect.size.height +4)

我在计算的高度上加了4px,因为没有这4px,就少了一行。

我在 tableView 中使用此代码 sn-p 并将“高度”添加到 NSNumbers 数组中,我得到了默认 textLabel 的正确单元格高度。

如果您想在 textLabel 中的文本下方增加 4 个像素。

**** 更新 ****

我不同意“40px的宽度错误”,我喊是缺少高度的4px,因为4px是字母和单行边界之间的空间的默认高度。 您可以使用 UILabel 进行检查,对于 16 的字体大小,您需要 20 的 UILabel 高度。

但如果您的最后一行没有“g”或其他任何内容,则测量可能会错过 4px 的高度。

我用一点方法重新检查了它,我得到的准确高度是 20,40 或 60 对于我的标签和小于 300 像素的右宽度。

要支持iOS6和iOS7,可以使用我的方法:

- (CGFloat)heightFromString:(NSString*)text withFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    float iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (iosVersion >= 7.0) {
        rect = [text boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
        CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
    }
    NSLog(@"%@: W: %.f, H: %.f", self, rect.size.width, rect.size.height);
    return rect.size.height;
}

****升级****

感谢你们的 cmets,我升级了我的功能如下。由于 sizeWithFont 已被弃用,并且您将在 XCode 中收到警告,因此我添加了 diagnostic-pragma-code 以删除此特定函数调用/代码块的警告。

- (CGFloat)heightFromStringWithFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
    CGRect rect;

    if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
        rect = [self boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil];
    }
    else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
        CGSize size = [self sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
        rect = CGRectMake(0, 0, size.width, size.height);
#pragma GCC diagnostic pop
    }
    return ceil(rect.size.height);
}

除了 4px 主题: 根据您使用的字体和字体粗细,计算会返回不同的高度值。在我的情况下:字体大小为 16.0 的 HelveticaNeue-Medium 单行返回 20.0 行高,但两行返回 39.0,4 行返回 78px -> 每行缺少 1px - 从第 2 行开始 - 但你想要为每一行设置你的字体大小 + 4px 行空间,你必须得到一个高度结果。
编码时请记住这一点!
我还没有解决这个“问题”的功能,但我会在完成后更新这篇文章。

【讨论】:

  • 您可能应该使用 [text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)] 而不是检查浮点值。
  • 最好用ceil函数而不是+4pt,看这个答案stackoverflow.com/a/23563152/667483
【解决方案2】:

@SoftDesigner 的评论对我有用

CGRect descriptionRect = [description boundingRectWithSize:CGSizeMake(width, 0)
                                                       options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                    attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}
                                                       context:nil];
result = ceil(descriptionRect.size.height);

【讨论】:

    【解决方案3】:

    如何创建新标签并使用sizeThatFit:(CGSize)size ??

    UILabel *gettingSizeLabel = [[UILabel alloc] init];
    gettingSizeLabel.font = [UIFont fontWithName:@"YOUR FONT's NAME" size:16];
    gettingSizeLabel.text = @"YOUR LABEL's TEXT";
    gettingSizeLabel.numberOfLines = 0;
    gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
    CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
    
    CGSize expectSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];
    

    编辑:上面的代码不适用于ios 7及以上,所以请在下面使用:

    CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                             options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
                             attributes:@{NSFontAttributeName:fontText}
                             context:nil];
    

    【讨论】:

    • 当我在字符串中添加 HTML 实体(如 (
        ,
      1. ) 时,此方法不起作用。
    • 请再次检查我的答案!我错过了 numberOfLines 属性!对不起!
    • 经过数小时的搜索、试验和死胡同,这是唯一适用于 iOS7 和 Xamarin / Monotouch 的解决方案
    • 创建标签来计算字体大小?太浪费了!
    • @Ossir,你有更好的主意吗?
    【解决方案4】:

    也许您需要为this 回答中建议的方法提供额外的选项:

    CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
    CGRect textRect = [myString boundingRectWithSize:maximumLabelSize   
                                             options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                          attributes:@{NSFontAttributeName: fontText}
                                             context:nil];
    

    【讨论】:

    • 看起来boundingRectWithSize 坏了。我在 iOS 7、7.1.1 上测试过,它返回的结果不正确。
    • 这对我不起作用,但是在 NSAttributedString 上使用 boundingRectWithSize 并将我的字体属性添加到字符串中确实有效。
    • 伙计们,别忘了 Apple 的声明:在 iOS 7 及更高版本中,此方法返回小数大小(在返回的 CGRect 的大小组件中);要使用返回的大小来调整视图大小,您必须使用 ceil 函数将其值提高到最接近的较高整数。
    • ceil 对我来说还不够,但发现使用 ceil 并添加 0.5 可以解决问题
    【解决方案5】:

    用于查找标签运行时的大小 sizewithfont 对于 iOS 7.0 已弃用,而您必须使用 -boundingRectWithSize:options:attributes:context: 方法

    你可以像下面的代码一样使用它

    CGSize constraint = CGSizeMake(MAXIMUM_WIDHT, TEMP_HEIGHT);
    NSRange range = NSMakeRange(0, [[self.message body] length]);
    
    NSDictionary *attributes = [YOUR_LABEL.attributedText attributesAtIndex:0 effectiveRange:&range];
    CGSize boundingBox = [myString boundingRectWithSize:constraint options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
    int numberOfLine = ceil((boundingBox.width) / YOUR_LABEL.frame.size.width);
    CGSize descSize = CGSizeMake(ceil(boundingBox.width), ceil(self.lblMessageDetail.frame.size.height*numberOfLine));
    
    CGRect frame=YOUR_LABEL.frame;
    frame.size.height=descSize.height;
    YOUR_LABEL.frame=frame;
    

    在这里,您必须将宽度指定为最大长度才能找到高度或宽度。

    试试这个它对我有用。

    【讨论】:

      【解决方案6】:

      如果我理解正确,您使用的是 boundingRectWithSize: 就像获取使用 sizeWithFont 获得的大小的一种方式(意味着您直接想要 CGSize,而不是 CGRect)?

      这看起来像你要找的东西:

      Replacement for deprecated sizeWithFont: in iOS 7?

      他们使用 sizeWithAttributes: 来获取大小,作为 sizeWithFont 的替代品。

      你是否仍然使用这样的东西得到错误的尺寸:

      UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
                          // you can use your font.
      
      expectedLabelSize = [myString sizeWithAttributes:@{NSFontAttributeName:fontText}];
      

      【讨论】:

      • 但是我如何使用 CGSize maximumLabelSize = CGSizeMake(310, 9999)?我需要正确的高度和宽度。
      • 是否有任何属性告诉 sizeWithAttributes: 限制其宽度/高度?
      • 对不起,我不明白你的问题是什么。如果我理解正确,您想用字体大小调整标签的大小,但不超过最大高度。您说您可以使用 sizeWithFont 来做到这一点,但您现在想要一个替代方法,因为该方法已被弃用,对吗?您应该能够以与使用 sizeWithFont: 相同的方式插入 sizeWithAttribues: 。当您使用 sizeWithFont 时,您是如何限制标签大小的?您可以使用 sizeWithFont 发布对您有用的代码吗?
      • 他使用的是 sizeWithFont:constrainedToSize:lineBreakMode: 并且无法将 constrainedToSize 值传递给 sizeWithAttributes。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多