StoryboardとStackViewでiPhone、iPadに対してそれぞれ専用レイアウトを作る。

# はじめに
あらためてXcodeを触る機会があり、真面目にAutoLayoutを勉強し直す、いい機会だったので色々試してみた。
やっぱViewはできる限りStoryboardに収めるべきだよねって感じで試行錯誤したので残しておく。

完成形のレイアウトは以下のような形
![スクリーンショット 2018-05-15 7.01.40.png](https://qiita-image-store.s3.amazonaws.com/0/50276/87a717d1-0fab-e423-bbcf-cb8b73353417.png)
iPhoneの縦表示とiPadの横表示それぞれでレイアウトを変えてStoryboardのみで表現する。

# 実行環境
Xcode9.3
Swift4.1
macOS High Sierra 10.13.4

# やったこと

## 1. まずはプロジェクトの作成から行ってください。
![スクリーンショット 2018-05-14 7.31.05.png](https://qiita-image-store.s3.amazonaws.com/0/50276/51395671-857f-fe4f-7599-aa0c764b6bb3.png)
![スクリーンショット 2018-05-14 7.31.42.png](https://qiita-image-store.s3.amazonaws.com/0/50276/5ac21b1b-afa4-2ddd-6dc9-1c42fd489817.png)

## 2. 縦横制御　
今回の前提レイアウトとしてはiPadは横のみ、iPhoneは縦のみにしたいので、Info.plistの「Suppoted interface orientations」を変更しましょう。
iPhone用、iPad用それぞれあるので、不要なものを削除します。
![スクリーンショット 2018-05-15 6.52.04.png](https://qiita-image-store.s3.amazonaws.com/0/50276/e9f33c5d-f11f-3173-3c82-ffe5a28e61ce.png)
※ちなみにPortraitが縦表示、Landscapeが横表示のことです。

## ３. StackViewでベース作成
レイアウトを作成するとき今回の場合は横をベースに作ると作りやすいので、
iPadの横をベースにします。
Storyboardの見た目を変更して作業します。
![スクリーンショット 2018-05-14 7.33.40.png](https://qiita-image-store.s3.amazonaws.com/0/50276/b2a96b06-8183-578e-342f-c164b27d894e.png)

StackViewを用意して、その中にViewを横に二つ並べそれぞれ、MainView(右・緑)、SubView(左・赤)を作成します。
![スクリーンショット 2018-05-14 7.35.49.png](https://qiita-image-store.s3.amazonaws.com/0/50276/e9cc14f3-e140-c2ae-0985-0a8ab857d44f.png)

※余談ですが、先にViewを追加している場合は以下の操作で、ViewをまとめてStackViweの中に入れてくれます。
![スクリーンショット_2018-05-14_7_36_092.png](https://qiita-image-store.s3.amazonaws.com/0/50276/7c5f699f-dd94-07d8-da33-11796d4a2d09.png)

StackViewに制約を追加して、画面サイズにぴったり合うように変更します。
上下左右を0で設定して制約を追加します。
![スクリーンショット 2018-05-14 7.38.07.png](https://qiita-image-store.s3.amazonaws.com/0/50276/750db5d6-8780-6a6b-b746-ec793afc089e.png)
※もし制約のかけ方を間違ってしまった場合は、右下のマークを押下して制約を消しましょう。
上の部分「Selected Views」は選択しているViewに付いている制約を消すことができます。
下の部分「All Views in View Controller」は選択しているViewControllerの全ての制約を消すことができます。
その時々で適切な方を使って制約を削除しましょう。
![スクリーンショット 2018-05-15 6.31.46.png](https://qiita-image-store.s3.amazonaws.com/0/50276/86f34cdf-86e3-e9c9-2829-556541c33892.png)

この状態で、一度Previewを見るとこんな感じです。
![スクリーンショット_2018-05-14_7_42_53.png](https://qiita-image-store.s3.amazonaws.com/0/50276/a3688efb-9e9c-acc0-1aef-59142bacc9df.png)
iPadはサイズが違くてもちゃんと並んでいるのがわかると思います。
iPhoneはまだできていません。

## 4. ベースの比率を設定する。
次に、StackViewの中に入っているViewの表示比率を変更します。
今回は、StackViewに対して等分にしたいので、Distributuinを「Fill Equally」に設定
![スクリーンショット 2018-05-15 6.16.37.png](https://qiita-image-store.s3.amazonaws.com/0/50276/495bdf7a-de1c-ace4-c3a2-0064886e391b.png)

![スクリーンショット 2018-05-15 6.16.50.png](https://qiita-image-store.s3.amazonaws.com/0/50276/e1ccd04c-0808-b972-2115-0a36a4b916e9.png)

そうすることで、iPad、iPhone共に表示が等分されました。
![スクリーンショット 2018-05-15 6.17.28.png](https://qiita-image-store.s3.amazonaws.com/0/50276/64039934-c910-82e2-ccb0-044d2e4664b5.png)

## 5. MainViewを分割する
今度は先ほど行った作業と同じようにStackViewの中にImageViewとViewを縦に配置しそれぞれ、ImageView(上)、MiddleView(下・青)を作成します。
![スクリーンショット 2018-05-15 6.23.19.png](https://qiita-image-store.s3.amazonaws.com/0/50276/fb60e5d1-7270-0def-06f3-ffbbb4d22574.png)
ここでもStackViewに制約を追加して、MainViewと同じサイズになるように変更します。
![スクリーンショット 2018-05-15 6.26.01.png](https://qiita-image-store.s3.amazonaws.com/0/50276/873107b7-4426-72e7-368e-32c493f29151.png)

ここも等分にしたいので、Distributuinを「Fill Equally」に設定

これをPreViewで見るとこんな感じ。
それぞれ同じレイアウトになりベースが完成しました。
![スクリーンショット 2018-05-15 6.26.55.png](https://qiita-image-store.s3.amazonaws.com/0/50276/3ba681df-9c08-59c9-21de-23d604e1da5f.png)
※Gitで作業している人は、間違った時にやり直せるようにコミットしておくとやり直しがきくので便利です。

## 6. iPhoneレイアウトを作る
ここからiPhoneのみレイアウトを変えていきます。
さてレイアウトを変える前に基礎的な説明を先にします。
端末の種類によってサイズクラスの定義が存在していて、以下のようになっています。

| デバイス/向き | 横サイズクラス | 縦サイズクラス | 
| ---- | ---- | ---- |
| iPhone 8 Plus /縦 | Compact(wC) | Regular(hR) |
| iPhone 8 Plus /横 | Regular(wR) | Compact(hC) |
| iPhone X /縦 | Compact(wC) | Regular(hR) |
| iPhone X /横 | Compact(wC) | Compact(hC) |
| iPhone 8 /縦 | Compact(wC) | Regular(hR) |
| iPhone 8 /横 | Compact(wC) | Compact(hC) |
| iPhone SE /縦 | Compact(wC) | Regular(hR) |
| iPhone SE /横 | Compact(wC) | Compact(hC) |
| iPhone 4s /縦 | Compact(wC) | Regular(hR) |
| iPhone 4s /横 | Compact(wC) | Compact(hC) |
| iPad Pro 12.9/縦 | Regular(wR) | Regular(hR) |
| iPad Pro 12.9/横 | Regular(wR) | Regular(hR) |
| iPad Pro 10.5/縦 | Regular(wR) | Regular(hR) |
| iPad Pro 10.5/横 | Regular(wR) | Regular(hR) |
| iPad Pro 9.7/縦 | Regular(wR) | Regular(hR) |
| iPad Pro 9.7/横 | Regular(wR) | Regular(hR) |

C ... Compact
R ... Regular
w ... Width
h ... Height

サイズクラスについては今までのXcodeの経緯があるのですが、そんなもの知らなくても
[クラスメソッド](https://dev.classmethod.jp/references/ios8-trait-collection/)さんの表を見るとわかりやすいのでそちらを確認してください。

さて、これで、端末ごとにサイズクラスの定義があることがわかったと思います。
今回は最初に示した通り、iPadの横表示、iPhone縦表示でのレイアウトを作りたいので、以下２つでそれぞれ違うレイアウトが実現できれば対応できます。

・iPadの横　... Regular(wR) / Regular(hR)
・iPhoneの縦 ... Compact(wC) / Regular(hR)

すでにiPadは対応が終わっているので、iPhoneに対しての対応を行います。
と言っても難しいことはなくてMainViewに当たるStackViewのAxisを変更するだけです。

Axisの横にある「+」を押し、追加する条件を選択します。
今回は先ほど示したiPhoneの縦表示なので、WidthがCompactでHeightがRegularです。
![スクリーンショット 2018-05-15 6.56.35.png](https://qiita-image-store.s3.amazonaws.com/0/50276/35e28adc-df0e-174d-2dcb-6b59e91e618c.png)

追加したらVirticalをHorizontalに変更しましょう。
![スクリーンショット 2018-05-15 7.00.55.png](https://qiita-image-store.s3.amazonaws.com/0/50276/da52b350-e603-8f25-32a7-39cb75ded88b.png)

これをPreviewで見るとこんな感じです。
![スクリーンショット 2018-05-15 7.01.40.png](https://qiita-image-store.s3.amazonaws.com/0/50276/96d024e2-ee2b-cb48-7580-6596575cac05.png)

これでやりたいことができました。
完成です！

## 7. 余談

もう少し細かい変更をかけたい場合は同じ要領で、StackViewの他の要素を変更することで対応することも可能です。
また、もっと細かくという場合は今回のStackViewと「Vary for Traits」を利用して制約を制御してあげることで、対応できると思います。
簡単に機能の説明をしておくと、
まずは通常の制約とは分けて別の制約をかけたいDeviceを選択します。
下の方にある「Vary for Traits」を押して追加したい種類を選択します。
![スクリーンショット 2018-05-15 7.08.03.png](https://qiita-image-store.s3.amazonaws.com/0/50276/36380a9b-06bb-2cdb-7f35-c5df013bc95c.png)

この状態で制約の削除や追加をして、「Done Varying」を押下すると対応するDeviceのみ別の制約をかけることができます。
![スクリーンショット 2018-05-15 7.06.35.png](https://qiita-image-store.s3.amazonaws.com/0/50276/13432613-dc03-222b-30ac-118eacc1af93.png)

AutoLayoutでiPhone、iPad両方を意識した複雑な制約を作る場合は大きくこの２つの機能を使うとソースにコードを書かなくてもAutoLayoutで実現できる場合が多いです。
ぜひ試してみてください。

# 最後に

今回のソースはGitHubに上がってますので参考にどうぞ。
https://github.com/nemui-fujiu/autolayout_for_iphone_and_ipad

参考
https://qiita.com/kukimo/items/fcfafe5c50efb84daf44