27

文字列の長さが指定された 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) なぜこのメソッドを削除するのですか? この別の方法との重複のためですか?

4

4 に答える 4

14

この一連の NSString+UIKit 関数は、スレッドセーフではない UIStringDrawing ライブラリに基づいていたため、この関数は非推奨になったと思います。メイン スレッド以外で実行しようとすると (他の UIKit 機能と同様)、予期しない動作が発生します。特に、関数を複数のスレッドで同時に実行すると、アプリがクラッシュする可能性があります。これが、iOS 6 でboundingRectWithSize:...NSAttributedStrings のメソッドが導入された理由です。これは NSStringDrawing ライブラリの上に構築されており、スレッドセーフです。

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

その点で、iOS 6 と iOS 7 のみをサポートしている場合は、すべての NSStringsizeWithFont:...を 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);
于 2013-09-23T03:26:44.127 に答える
3

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

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
于 2016-05-21T07:12:07.773 に答える