AutoLayoutの≧≦系制約の判断方法
却下されるときに遺言を残す?
AutoLayoutのcontraintの
- greaterThanOrEqualTo
- lessThanOrEqualTo
で与える制約は、値がどのように決まるのか謎でした。それはつまり、100以上という制約があるときに(他の決定させる制約がなければ)120と150と180はどれも同じように条件を満たすので、その範囲の中からどのように値が決定するのかということです。しかし最近、少しわかったことがあったので書く。
確かめたこと
あるUIViewの横幅に制約をつける。制約は
- 100以上
- 200以下
- 10固定
- 1000固定
の4つ。このうち
- 100以上と、200以下は常時有効。プライオリティは1000。
- 10固定と1000固定は有効/無効を切り替えたり、プライオリティを下げたりする。
いくつかのパターンを調べることで、「以上」「以下」の制約がどう扱われるか見ていく。
Xcode 11.5 ストーリボード上で操作
100以上、200以下
100以上、200以下、固定値10(p: 1000)
100以上、200以下、固定値10(p: 999)
100以上、200以下、固定値1000(p: 1000)
100以上、200以下、固定値1000(p: 999)
100以上、200以下、固定値10(p: 999)、固定値1000(p: 999)
100以上、200以下、固定値10(p: 998)、固定値1000(p: 999)
100以上、200以下、固定値10(p: 999)、固定値1000(p: 998)
結論
上の例では、ぎりぎり採用されなかった制約の影響を受けて、広い範囲の中の1点に決定している。
ソースコードだと
ストーリボードではエラー表示になるものも、ソースで書いて実行するとエラーを目にすることがない。
感想
今までは、制約が衝突したときはプライオリティが低いものから順に無視されて行き、衝突が無くなったら確定という理解だったんだけど、無視されるものは完全に無視されるのではなく、遺言(?)を残すということがわかった。
また、ソースで制約を書く人はダメなことをやっていても叱ってくれる人がいないので気が付きにくい。
今回わかったことを法則として頭に入れておくことにより、次のような状況のとき、
- あるシンプルな計算による結果で、20から80まで変わるもの(A)
- 最低40は確保したい(B)
Bのプライオリティを1000、Aをそれより低くしたら思うようにいくことに確信がもてるし、なぜうまくいくのか悩まなくていい。
全ての値決定アルゴリズムがわかったわけではないが、なかなかの前進であった。
追記
lessのみシンプルなパターンも検証してみた。