出典:http ://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
複数行のテキストの固有のコンテンツサイズ
UILabelとNSTextFieldの固有のコンテンツサイズは、複数行のテキストではあいまいです。テキストの高さは線の幅に依存しますが、これは制約を解決するときにまだ決定されていません。この問題を解決するために、両方のクラスに、preferredMaxLayoutWidthという新しいプロパティがあります。これは、固有のコンテンツサイズを計算するための最大線幅を指定します。
通常、この値は事前にわからないため、これを正しく行うには2段階のアプローチをとる必要があります。最初に自動レイアウトに作業を任せ、次にレイアウトパスで結果のフレームを使用して、優先される最大幅を更新し、レイアウトを再度トリガーします。
- (void)layoutSubviews
{
[super layoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[super layoutSubviews];
}
[super layoutSubviews]の最初の呼び出しは、ラベルがフレームセットを取得するために必要ですが、2番目の呼び出しは、変更後にレイアウトを更新するために必要です。2番目の呼び出しを省略すると、制約の更新を必要とするレイアウトパスに変更を加えたため、NSInternalInconsistencyExceptionエラーが発生しますが、レイアウトを再度トリガーしませんでした。
これは、ラベルサブクラス自体でも実行できます。
@implementation MyLabel
- (void)layoutSubviews
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[super layoutSubviews];
}
@end
この場合、最初に[super layoutSubviews]を呼び出す必要はありません。これは、layoutSubviewsが呼び出されたときに、ラベル自体にすでにフレームがあるためです。
ビューコントローラレベルからこの調整を行うには、viewDidLayoutSubviewsにフックします。この時点で、最初の自動レイアウトパスのフレームはすでに設定されており、それらを使用して優先最大幅を設定できます。
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[self.view layoutIfNeeded];
}
最後に、ラベルのコンテンツ圧縮抵抗の優先度よりも高い優先度を持つ明示的な高さの制約がラベルにないことを確認してください。それ以外の場合は、コンテンツの計算された高さよりも優先されます。ラベルの高さに影響を与える可能性のあるすべての制約を確認してください。