最近知って感動したAutoLayoutTips
注意:きちんと公式情報で裏取ってません
注意:iOS8切れる方はStackView使ってどうぞ
シーン
下の図のような状況で、View2をhiddenにしたい(AutoLayout使う)
hiddenにするときは、View1とView3をくっつけたい
ああ面倒くさい、こういうのはAndroidだと楽なのに
方法としては何パターンか思いつきますが、とりあえず3つ
1.可能ならTableViewにしてしまう
2.View1-View2、View2-View3、View1-View3で制約を設け
View1-View3の優先度を下げておく
View2をhiddenにしたいときhiddenにしたい時は
View2-View3の優先度を下げ、View1-View3の優先度を上げる
なんかスマートだけど、制約が込み入るとか、View2を起点にして他の制約があると全部調整しなきゃいけないから厄介
3.View2の高さの制約を変数として持っておいて、hidden時に高さをゼロにしてしまう
割りと取られるのは3じゃないかと思います
そしてその後で
でも状況によってhidden解除しなきゃいけない!!
となり
あ、元の高さの値を保存しておかなきゃ!
となり
でもコード内に定義するとstoryboardと定義が分散して怖いな
じゃあ制約から値を取り出そう!
でももとの値っていつどこで保存するんだっけ? ViewdidLoad? viewDidLayoutSubviews? あれ?? こいついつもゼロだぞ・・・
と悩むことが多いです(私だけ?)
解決策
要点
・viewDidLoadの、[super viewDidLoad]の前で取得可能
・NSLayoutConstraintにはidentifierが付けられる(知らなかった!!)
つまりこうです
高さの制約を繋ぎこみます
高さの制約のidentifierを設定します
制約の親viewを繋ぎこみます(view2)
保持する変数を用意します(defaultView2Height)
viewの持っているNSLayoutConstraintは、view.constraintsにすべて入っているので
そこからidentifierで該当制約を取り出します
これで該当制約の初期値(storyboardで設定した値)を安全に保持できます(やったぜ)
でも[super viewDidLoad]の前に処理をゴリゴリ書くのは正直嫌なので
Categoryやらextensionやらにして一行で書いてしまえばよいですね
一応言うとこの方法もちょっとデメリットが有り
制約を一度消して再作成する際などは、identifierの再設定を忘れそうです
(まあテストすればわかるんですけど、エラーにはならない)
とりあえずidentifierの命名規則は統一しておきたいですね(親View名+Heightとか)
わからなくなるとヤバイので
以上です
追記:
self.viewのsubviews配下の制約を全部洗ってしまえば、画面内のidentifierが付いている全制約の初期値を保持しておけますね
例えばidentifierをkeyにして、初期設定値を一個のdictionaryに詰めるとかしたら
必要なときに呼び出すだけとかできて便利かもしれません
利用シーンがあればですが