文字列の長さ(対応する正しいフォントサイズ)を指定すると、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)この方法を削除する理由これは、この他の方法と重複しているためですか?
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);
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);
改行の問題の場合:
- (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);
}
ノルウェーのアレキサンダーの答えの迅速なバージョン...
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