1. ホーム
  2. ios

[解決済み] UIViewに影響するすべての制約を取り除く

2023-01-09 21:28:25

質問

いくつかの制約を介して画面上に配置されるUIViewがあります。制約のいくつかはスーパービューによって所有され、その他は他の祖先によって所有されます(たとえば、UIViewControllerのviewプロパティなど)。

これらの古い制約をすべて削除し、新しい制約を使用して新しい場所に配置したいと思います。

1つ1つの制約に対してIBOutletを作成し、どのビューがその制約を所有しているかを覚えることなく、これを行うにはどうしたらよいですか?

詳しく説明すると、素朴なアプローチは、各制約のために多くのIBOutletを作成することであり、その後、次のようなコードを呼び出すことを含むでしょう。

[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];

このコードの問題は、最も単純なケースでも2つのIBOutletsを作成する必要があることです。複雑なレイアウトの場合、必要なIBOutletは簡単に4つまたは8つに達する可能性があります。さらに、制約を取り除くための呼び出しが、適切なビューで呼び出されていることを確認する必要があります。例えば、次のように想像してください。 myViewsLeftConstraint が所有する viewA . もし私が誤って [self.view removeConstraint:self.myViewsLeftConstraint] を誤って呼んでしまっても、何も起こりません。

注意してください。 メソッド constraintsAffectingLayoutForAxis は有望に見えますが、デバッグのためだけのものです。


更新しました。 私が受け取っている多くの回答は self.constraints , self.superview.constraints またはそれらのいくつかのバリエーションです。これらのメソッドは制約だけを返すので、これらの解決策はうまくいきません。 所有 ではなく、ビューによって に影響する に影響を与えるものではありません。

これらの解決策の問題点を明らかにするために、このビュー階層を考えてみましょう。

  • グランドファーザー
        • 息子
      • 兄弟
    • おじさん

今、以下の制約を作成し、常に最も近い共通の祖先に添付することを想像してみてください。

  • C0: Me: Son と同じトップ (Me が所有)
  • C1: 私: 幅 = 100 (私の所有物)
  • C2: 私:兄と同じ高さ(父所有)
  • C3:私:叔父と同じ上半身(祖父所有)
  • C4:私:お爺さんと同じ左(お爺さん所有)
  • C5:弟:父と同じ左(父が所有)
  • C6:叔父:祖父と同じ左(祖父が所有)
  • C7: 息子:娘と同じ左側(私が所有)

次に、次のような制約をすべて取り除くとします。 Me . 適切な解決策であれば [C0,C1,C2,C3,C4] を削除し、それ以外は何もしないことです。

もし私が self.constraints (selfはMe)とすると、以下のようになります。 [C0,C1,C7] を取得します。これらはMeによって所有される唯一の制約であるためです。明らかに、これが欠けているので、これを削除するだけでは十分ではないでしょう。 [C2,C3,C4] . さらに、それは C7 を不必要に削除しています。

もし私が self.superview.constraints (selfはMe)とすると、以下のようになります。 [C2,C5] を得ます。これらは父が所有する制約だからです。明らかに、私たちはこれらすべてを取り除くことはできません。 C5 とは全く関係なく Me .

もし私が grandfather.constraints とすると [C3,C4,C6] . ここでも、これらすべてを削除することはできません。 C6 はそのまま残っていなければならないので、これらすべてを削除することはできません。

ブルートフォースアプローチは、ビューの祖先(自分自身を含む)のそれぞれをループして、もし firstItem または secondItem がビュー自身である場合、その制約を取り除きます。これは正しい解決策を導き、 [C0,C1,C2,C3,C4] を、そしてそれらの制約だけを返す、正しい解決につながります。

しかし、先祖のリスト全体をループするよりも、よりエレガントなソリューションがあることを期待しています。

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

私が今までに見つけた唯一の解決策は、そのスーパービューからビューを削除することです。

[view removeFromSuperview]

これは、レイアウトに影響を与えるすべての制約を削除し、スーパービューに追加し、新しい制約を追加する準備ができているように見えます。しかし、階層からすべてのサブビューを誤って削除し、また [C7] のように、正しく表示されます。