1. ホーム
  2. iphone

[解決済み] UIViewのsetNeedsLayout、layoutIfNeeded、layoutSubviewsの関係は?

2022-11-15 07:39:56

質問

の関係について、どなたか明確な説明をお願いします。 UIView's setNeedsLayout , layoutIfNeededlayoutSubviews メソッドを使用できますか?また、この3つのメソッドが使用される実装例についても教えてください。ありがとうございます。

何が私を混乱させるかというと、カスタムビューに setNeedsLayout メッセージを送ると、このメソッドの次に呼び出されるのが layoutSubviews を飛び越え layoutIfNeeded . ドキュメントを見る限りでは、次のような流れになると思われます。 setNeedsLayout 原因 layoutIfNeeded が呼び出されるようにする > 原因 layoutSubviews が呼び出されるようにする。

どのように解決するのですか?

私はまだこれを自分自身で理解しようとしているので、いくつかの懐疑的な態度でこれを取り、それがエラーを含んでいる場合、私を許してください。

setNeedsLayout は簡単なものです。UIView のどこかに、レイアウトが必要であるとマークするフラグを設定するだけです。 それは強制的に layoutSubviews が呼び出されるようになります。 多くの場合、これを明示的に呼び出す必要はないことに注意してください。 autoresizesSubviews プロパティのためです。 それが設定されている場合(デフォルトではそうなっています)、ビューのフレームへの変更は、ビューがそのサブビューをレイアウトすることを引き起こします。

layoutSubviews は、すべての興味深いことを行うメソッドです。 これは drawRect と同じです。 些細な例ですが、次のようになります。

-(void)layoutSubviews {
    // Child's frame is always equal to our bounds inset by 8px
    self.subview1.frame = CGRectInset(self.bounds, 8.0, 8.0);
    // It seems likely that this is incorrect:
    // [self.subview1 layoutSubviews];
    // ... and this is correct:
    [self.subview1 setNeedsLayout];
    // but I don't claim to know definitively.
}

参考までに layoutIfNeeded は一般にサブクラスでオーバーライドされることを意図していません。 これは、ビューをレイアウトするときに呼び出されるメソッドです。 今すぐ . Appleの実装はこのような感じでしょうか。

-(void)layoutIfNeeded {
    if (self._needsLayout) {
        UIView *sv = self.superview;
        if (sv._needsLayout) {
            [sv layoutIfNeeded];
        } else {
            [self layoutSubviews];
        }
    }
}

あなたは layoutIfNeeded を呼び、そのビュー (および必要に応じてそのスーパービュー) を直ちにレイアウトするように強制します。