1. ホーム
  2. アイオス

[解決済み】setNeedsLayout と setNeedsUpdateConstraints の比較と layoutIfNeeded と updateConstraintsIfNeeded の比較

2022-04-03 04:54:08

質問

オートレイアウトチェーンは、基本的に3つのプロセスで構成されていることは知っています。

  1. 制約の更新
  2. レイアウトビュー(ここでフレームの計算が発生します)
  3. 表示

との違いがよくわからない。 -setNeedsLayout-setNeedsUpdateConstraints . Apple Docsより。

setNeedsLayout

このメソッドは、アプリケーションのメインスレッドで呼び出します。 ビューのサブビューのレイアウトを調整します。このメソッドは を要求し、すぐに返します。このメソッドは 次の更新まで待ちます。 サイクルでは、複数のビューのレイアウトを無効にするために使用することができます。 を使用すると、これらのビューのいずれかが更新される前に、これらのビューを更新することができます。この動作により、以下のことが可能になります。 レイアウトの更新はすべて1回の更新サイクルにまとめられるので、その方がよい。 は、通常、パフォーマンスにとってより良いものです。

setNeedsUpdateConstraintsを設定します。

カスタムビューのプロパティが変更され、それが 制約があることを示すために、このメソッドを呼び出すことができます。 は、将来のある時点で更新される必要があります。すると、システムは は、通常のレイアウトパスの一部として 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-オートレイアウトについての必読書-によると :

<ブロッククオート

後で何かが変更されて制約の1つが無効になった場合、制約を直ちに削除して、setNeedsUpdateConstraintsを呼び出す必要があります。 実際、制約の更新パスを起動する必要があるのは、この場合だけです。

また、私の経験では、制約を無効化することで、設定しないまま setNeedsLayout というのも、新しい制約はかなり新しいレイアウトを要求しているからです。

経験則から言うと

  • 制約を直接操作した場合は setNeedsLayout .
  • オフセットやその他の条件を変更した場合は、以下のようになります。 となる をオーバーライドして制約を変更します。 updateConstraints メソッド(制約を変更する推奨される方法です。 setNeedsUpdateConstraints , そしてほとんどの場合 setNeedsLayout その後
  • 上記のアクションをすぐに実行したい場合、例えば、レイアウトパスの後に新しいフレームの高さを学習する必要がある場合、このアクションに layoutIfNeeded .

また、あなたのアニメーションのコードでは、確か setNeedsUpdateConstraints なぜなら、制約はアニメーションの前に手動で更新され、アニメーションは古いものと新しいものの間の差異に基づいてビューを再レイアウトするだけだからです。