web-dev-qa-db-ja.com

廃止予定のsizeWithFontの置き換え:iOS 7?

IOS 7では、sizeWithFont:は現在非推奨です。どうやってUIFontオブジェクトを置き換えメソッドsizeWithAttributes:に渡すことができますか?

318
James Kuang

代わりに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));
517
James Kuang

この一連のNSString+UIKit関数(sizewithFont:...など)は、スレッドセーフではないUIStringDrawingライブラリに基づいているため、この関数は推奨されなくなりました。メインスレッドではなく他のUIKit機能のようにそれらを実行しようとすると、予期しない動作をするでしょう。特に、同時に複数のスレッドで関数を実行した場合、おそらくアプリケーションがクラッシュします。これがiOS 6で彼らがNSAttributedStringに対してboundingRectWithSize:...メソッドを導入した理由です。これはNSStringDrawingライブラリの上に構築されており、スレッドセーフです。

新しいNSStringboundingRectWithSize:...関数を見ると、NSAttributeStringと同じ方法で属性配列を要求します。私が推測しなければならないのは、iOS 7のこの新しいNSString関数は、iOS 6のNSAttributeString関数の単なるラッパーです。

そのメモでは、もしあなたがiOS 6とiOS 7だけをサポートしているのなら、私はあなたのNSStringsizeWithFont:...すべてをNSAttributeStringboundingRectWithSizeに確実に変更します。あなたが奇妙なマルチスレッドコーナーケースを持っていることが起こるならば、それはあなたに多くの頭痛を救うでしょう!これがNSStringsizeWithFont: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);
172
Mr. T

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

この問題を処理するためのカテゴリを作成しました。

#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:で見つけたり置き換えたりしさえすればいいのです。

16
Rom.

IOS 7では、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
10
user3055587

動的な高さを使用する複数行のラベルでは、サイズを正しく設定するための追加情報が必要になる場合があります。 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];

あなたが高さを探しているならあなたはrect.size.heightプロパティとしてCGSize '調整済みサイズ'またはCGRectを使うことができます。

NSParagraphStyleについてのより詳しい情報はここにあります: https://developer.Apple.com/library/mac/documentation/cocoa /参照/ applicationkit/classes/NSParagraphStyle_Class /参照/参照.html

7
bitsand
// 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));
4
Kirit Vaghela

代替ソリューション -

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

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

結果のフレームのサイズをそのまま使用します。

3
Chris Prince

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;
3
Muhammad Idris

あなたはまだsizeWithFontを使うことができます。ただし、iOS> = 7.0のメソッドでは、文字列の前後にスペースが含まれている場合や終了行に\nが含まれている場合にクラッシュします。

使用する前にテキストをトリミングする

label.text = [label.text stringByTrimmingCharactersInSet:
             [NSCharacterSet whitespaceAndNewlineCharacterSet]];

これはsizeWithAttributes[label sizeToFit]にも当てはまります。

また、あなたがiOS 7.0デバイスでnsstringdrawingtextstorage message sent to deallocated instanceを持っているときはいつでも、それはこれを扱います。

2
hasan

自動寸法の使用を改善しました(Swift):

  tableView.estimatedRowHeight = 68.0
  tableView.rowHeight = UITableViewAutomaticDimension

注意:1. UITableViewCellプロトタイプは適切に設計されている必要があります(例としてset UILabel.numberOfLines = 0などを忘れないでください)。2. HeightForRowAtIndexPathメソッドを削除します。

enter image description here

ビデオ: https://youtu.be/Sz3XfCsSb6k

2

認められた答え Xamarinでは/(sizeWithAttributesおよびUITextAttributeFontを使用)になります。

        UIStringAttributes attributes = new UIStringAttributes
        { 
            Font = UIFont.SystemFontOfSize(17) 
        }; 
        var size = text.GetSizeUsingAttributes(attributes);
1
boundingRectWithSize:options:attributes:context:
1
Holden

この構文を試してください:

NSAttributedString *attributedText =
    [[NSAttributedString alloc] initWithString:text 
                                    attributes:@{NSFontAttributeName: font}];
0
Muruganandam.S

@Ayushの回答として:

Apple Developerサイトで sizeWithFont を見ることができるようにそれは非推奨ですので sizeWithAttributes を使う必要があります。

さて、2019年以降にObjective-cとStringの代わりに Swift NSStringを使用していると仮定して、定義済みのフォントでStringのサイズを取得する正しい方法は次のとおりです。

let stringSize = NSString(string: label.text!).size(withAttributes: [.font : UIFont(name: "OpenSans-Regular", size: 15)!])
0
Romulo BM

誰かがそれを必要とするならば、これはモノタッチ同等物です:

/// <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);
}
0
Roosevelt
CGSize maximumLabelSize = CGSizeMake(label.frame.size.width, FLT_MAX);
CGSize expectedLabelSize = [label sizeThatFits:maximumLabelSize];
float heightUse = expectedLabelSize.height;
0
user1802778
- (CGSize) sizeWithMyFont:(UIFont *)fontToUse
{
    if ([self respondsToSelector:@selector(sizeWithAttributes:)])
    {
        NSDictionary* attribs = @{NSFontAttributeName:fontToUse};
        return ([self sizeWithAttributes:attribs]);
    }
    return ([self sizeWithFont:fontToUse]);
}
0