自動レイアウトチェーンは基本的に3つの異なるプロセスで構成されています。
私にとってはっきりしないのは、-setNeedsLayout
と-setNeedsUpdateConstraints
の内部の違いです。 Apple Docsから:
ビューのサブビューのレイアウトを調整したい場合は、アプリケーションのメインスレッドでこのメソッドを呼び出します。このメソッドはリクエストを記録してすぐに戻ります。このメソッドは即時の更新を強制するのではなく、代わりに次の更新サイクルを待つため、これらのビューのいずれかが更新される前に複数のビューのレイアウトを無効にするために使用できます。この動作により、すべてのレイアウト更新を1回の更新サイクルに統合することができます。これは通常、パフォーマンスの点で優れています。
カスタムビューのプロパティが制約に影響を与えるような方法で変更された場合は、このメソッドを呼び出して、将来のある時点で制約を更新する必要があることを示すことができます。システムは通常のレイアウトパスの一部としてupdateConstraintsを呼び出します。制約が必要になる直前に一度に更新することで、レイアウトパスの間にビューに複数の変更が加えられたときに、不必要に制約を再計算する必要がなくなります。
制約を変更した後にビューをアニメートし、変更をアニメートしたい場合は、たとえば次のようにします。
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
-setNeedsLayout
の代わりに-setNeedsUpdateConstraints
を使用するとすべてが期待通りに動作することがわかりましたが、-layoutIfNeeded
を-updateConstraintsIfNeeded
に変更するとアニメーションは発生しません。
私は自分自身の結論を出すことを試みました:
-updateConstraintsIfNeeded
は制約を更新するだけですが、レイアウトがプロセスに入るよう強制することはしません。したがって、元のフレームはそのまま維持されます。-setNeedsLayout
は-updateContraints
メソッドも呼び出しますそれでは、いつ他のものの代わりにどちらを使用してもよいですか?レイアウトメソッドについては、制約が変更されたビューまたは親ビューでそれらを呼び出す必要がありますか。
あなたの結論は正しいです。基本的なスキームは:
setNeedsUpdateConstraints
は、今後updateConstraintsIfNeeded
への呼び出しがupdateConstraints
を呼び出すようにします。setNeedsLayout
は、今後layoutIfNeeded
への呼び出しがlayoutSubviews
を呼び出すようにします。layoutSubviews
が呼び出されると、updateConstraintsIfNeeded
も呼び出されるため、経験上、手動で呼び出す必要はほとんどありません。実際、レイアウトをデバッグするときを除いて、これを呼び出したことがありません。
setNeedsUpdateConstraints
を使用して制約を更新することも非常にまれです。 objc.io–aはautolayouts–saysについて読む必要があります :
後で何かが変更されて制約の1つが無効になった場合は、すぐに制約を削除してsetNeedsUpdateConstraintsを呼び出す必要があります。 実際、これが制約更新パスをトリガーする必要がある唯一のケースです。
さらに、私の経験では、制約を無効にする必要はなく、コードの次の行にsetNeedsLayout
を設定しませんでした。新しい制約が新しいレイアウトを要求しているためです。
経験則は次のとおりです。
setNeedsLayout
を呼び出します。updateConstraints
メソッドの制約を変更するwouldする条件(オフセットやsmthなど)を変更した場合(制約を変更する推奨方法、btw)、setNeedsUpdateConstraints
、そしてほとんどの場合、setNeedsLayout
その後。layoutIfNeeded
を追加します。また、アニメーションコードでは、setNeedsUpdateConstraints
は不要であると考えています。これは、アニメーションが手動で更新される前に制約が更新され、アニメーションは古いものと新しいものの違いに基づいてビューを再レイアウトするだけだからです。
カバーバックによる回答 はかなり正しいです。ただし、詳細をいくつか追加したいと思います。
以下は、他の動作を説明する典型的なUIViewサイクルの図です。
-setNeedsLayout
の代わりに-setNeedsUpdateConstraints
を使用するとすべてが期待通りに動作することがわかりましたが、-layoutIfNeeded
を-updateConstraintsIfNeeded
に変更してもアニメーションは発生しませんupdateConstraints
は通常何もしません。 layoutSubviews
が呼び出されるまでは適用されない制約を解決するだけです。そのため、アニメーションではlayoutSubviews
を呼び出す必要があります。
いいえ、これは必要ありません。制約が変更されていない場合、UIViewはupdateConstraints
への呼び出しをスキップします。プロセス内の制約を変更するには、setNeedsUpdateConstraint
を明示的に呼び出す必要があります。
updateConstraints
を呼び出すには、次の手順を実行する必要があります。
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];