既存アプリのAuto Layout対応を行ってみた
Tinysquare for foursquare をiOS10対応を実施してAppleへ申請を行いました。
iOS10がリリースされてそろそろ1ヶ月が経つわけですが、Tinysquare は Apple Watch 対応を実施してからほとんど対応をしていなかったので、そろそろ次のバージョンアップをしないといけないと思ったわけです。
とはいえ、実質iOS7くらいまでしか対応をしていなかったので、対応しないといけないことは多い。
とりあえず一回全部対応するんだけど、一番やっかいそうなのが Auto Layout でした。
でもこれが一番やりたかった対応。それは iPad Multitasking に対応したかったから。これで Safari いじってる途中にチェックイン画面を出せる。画面の分割だってできる。
対応して気づいたことをまとめてみる。
Auto Layout
Auto Layout は Constraint(制約)と呼ばれる要素間の関係を定義することでレイアウトを設定する。
要は関係性のルールを決めることで画面サイズが変わっても同じ関係で配置がされるということ。
実際にどういう Constraint があるかは以下を読んでざっと理解。一通り網羅されているので良いです。
Constraint 設定する前にどうレイアウトするかの全体像を決めよう
View の配置は結局のところ [x, y, width, height] を決めれば確定するわけだけど、これを固定でやってしまえば可変にできない。
なので、これを要素間の関係で決める、基本的には親の要素であるトップの View をベースに決めるを考えていく。
また、サイズが変わるのでどこかの幅と高さは可変にしないといけない。ただなんでも可変にすると非常に難しいので、可変とする View を事前に決めていく。
実際に決めた内容
こちらがチェックインを行うための画面。左右は親の View から 20 離す(スペースを取る)ことを基本とする。
カテゴリのアイコンとチェックイン場所の名前のように一列に並ぶものはそれぞれのスペースを制約として設定する。
アイコンは固定幅のものを表示するので、幅と高さは固定。そうすることで、名前の幅は可変となる(左のアイコンと右の親Viewとの関係で決まる)
iPhoneの各モデルごとによる縦方向の変化は、コメントとMapのViewを可変にすることで調整する。それ以外はアイコンなどで固定の高さなので。
2つのViewの高さを可変にする場合、その2つのViewの関係を決めると対応しやすい。今回はそれぞれの高さが常に同じになるように制約を設定した。
一覧画面は UITableView と MKMapView の高さがそれぞれ可変。それぞれが 2:1 になるような制約を設定している。
Constraint の設定は上の要素から順番に実施しよう
レイアウトの方針が決まったら、それにあわせて一つずつ設定していく。
ちなみにXcodeで自動で設定してくれる機能(Add Missing Constraints)もあるが、使うとわけが分からなくなる。
どういうルールでその制約を入れたかが正直良くわからないため。
なので、地道に自分で一つずつ設定していくことをおすすめする。
左上のViewから順番に赤や黄色になる状態をなくしていく。Storyboard も基本的には上から計算して配置するようなのでそれにあわせて上から順番に。
Storyboard で反映されないことがある
一度設定が済めばどの画面サイズでもちゃんと反映される。ただ、Storyboardでなぜかエラーになる場合がある。
そんなとき View のサイズが [0, 0, 1000, 1000] という値になってしまっている。
おそらくはこの値を初期値として計算をしていく。どこかでハマった場合にそうなるっぽい。(何か設定でそうならないようにできるのかもしれないけど)
そんなときは面倒だけど、幅と高さをいったん 0 にした。そうするとエラーを示す赤から警告の黄色に変わる。その上で Update Frames を全てに適用するとちゃんと設定される。
まとめ
Constraint(制約)という言葉が分かりにくいけど、一度やってみると基本的な構想は理解できる。
まだ Dynamic Type にも対応していないので、奥の深い部分はまだまだだとは思うけど。
Trait Collection にも対応しているので、ひとつのStoryboardでiPhoneもiPadも対応できたし良しとしよう。