2013-08-19 17 views
26

I持っている(対応する正しいフォントサイズで)私に、文字列の長さを与えUITextViewのための完璧なサイズを与える方法:deprecated sizeWithFont:メソッドに代わるものは何ですか?

- (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を使用しなければならないと言う:オプション:属性:コンテキスト:

この方法はiOS7に新しいものではありませんので、私はスタックオーバーフローでそれを聞いても大丈夫であることを理解し、よりもむしろ行きます正式なアップル開発者フォーラムに向かいます。

私は3つの質問を持っている:

1)それは推奨されませんので、それは私は間違いなく、それはまだ作業にもかかわらず、それを置き換える必要があります意味ですか?

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

3)なぜこのメソッドを削除しますか?この他の方法との重複のためですか?

+0

は、この[リンク](http://www.cnblogs.com/lisa090818/p/3445161.htmlを参照してください。 )。 – yazh

+1

wtfはそのリンクですか? – Rambatino

答えて

57

は裁判エラーの時間後、私はそれを動作させるために管理:

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

ありがとうございます。私はあなたが作成したstringAttributes辞書を使用してNSAttributedStringを作成し、属性付き文字列にboundingRectWithSize:options:context:を呼び出すiOS6と同様のものを使用しています。 – AidenMontgomery

+0

あなたより!本当に便利です! – Andres

13

私は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); 
+4

アドレスの改行モードの問題を解決しない – Firdous

+0

下記の私の答えを参照してください。 –

5

:の

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

スウィフトバージョンノルウェーの答えのアレクサンダー...

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