web-dev-qa-db-ja.com

非推奨のsizeWithFont:メソッドを何に置き換えればよいですか?

文字列の長さ(対応する正しいフォントサイズ)を指定すると、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;
}

実際、iOS7であっても、それでも完璧にフィットします。今では、 'sizeWithFont:contrainedToSize:lineBreakMode'を使用するべきではないという警告メソッドがあります。

現在、-boundingRectWithSize:options:attributes:contextを使用する必要があると表示されます。

この方法はiOS7にとって新しいものではないため、公式のApple開発者フォーラムに行くのではなく、スタックオーバーフローでそれを尋ねても問題ありません。

3つの質問があります。

1)非推奨であるため、まだ機能しているにもかかわらず、確実に置き換える必要があるということですか?

2)私は多くの異なるboundingRectWithSize:メソッドを試しましたが、さまざまな変数を使用しましたが、完璧ではない、それは常にわずかに外れているようです(多くのstackoverflowの質問が指摘しているように)-最小限の手間で私の以前の方法と同じですか?

3)この方法を削除する理由これは、この他の方法と重複しているためですか?

26
Rambatino

1時間の試行錯誤の後、私はそれをうまく機能させることができました:

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

更新:

T氏が以下の回答で言及しているように:iOS 7以降では、このメソッドは小数サイズを返します(返されたCGRectのサイズコンポーネントで)。返されたサイズを使用してビューのサイズを変更するには、その値を上げる必要がありますceil関数を使用して、最も近い高い整数に変換します。ceilf関数を使用することをお勧めします。

CGFloat height = ceilf(labelBounds.size.height);
57
Rambatino

NSString + UIKitの一連の関数は、スレッドセーフではないUIStringDrawingライブラリに基づいていたため、この関数は廃止されたと思います。メインスレッド上ではなく(他のUIKit機能のように)実行しようとすると、予測できない動作が発生します。特に、複数のスレッドで同時に関数を実行すると、おそらくアプリがクラッシュします。これが、iOS 6でNSAttributedStringsに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:CGSizeMake(width, CGFLOAT_MAX)];

に置き換えることができます:

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;

ドキュメントの言及に注意してください:

IOS 7以降では、このメソッドは小数サイズを返します(返されるCGRectのサイズコンポーネント)。返されたサイズを使用してビューのサイズを変更するには、ceil関数を使用して値を最も近い整数に上げる必要があります。

したがって、ビューのサイズ設定に使用する計算された高さまたは幅を引き出すには、次を使用します。

CGFloat height = ceilf(size.height);
CGFloat width  = ceilf(size.width);
13
Mr. T

改行の問題の場合:

- (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);
}
5

ノルウェーのアレキサンダーの答えの迅速なバージョン...

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

高さを取得するコードでは、次のようなメソッドを呼び出すだけです...

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
2
Koti Tummala