iPhone
Xcode
iOS
AutoLayout
Swift

iPhone Xとその他の画面で余白を切り替える

問題

こちらにも投稿したように、Xcode9からはStoryboardにSafeAreaという概念が追加されており、比較的簡単にiPhoneXの画面に対応ができます。
しかし、自前のViewを画面の最下部に合わせて配置する場合、iPhoneXのSafeAreaに合わせたViewコンテンツ配置の場合と、その他の画面の場合で高さや縦方向のマージンを切り替えたい場合があったので、どうやって対応したかを記します。

まず、説明だけではわかりにくいと思うのでどういうことかを画像付きで説明します。

スクリーンショット 2017-10-24 18.32.25.png スクリーンショット 2017-10-24 18.32.40.png

オレンジのエリアは背景がBlurになっているViewです。
iPhoneXの場合は画面の端までBlurを引き伸ばしたいので、購入ボタンの下のマージンが増え、オレンジのエリアのViewの高さが高くなっています。

実装方法

ロジックから分岐するなどいくつか方法はあると思いますが、今回はStoryboard上だけで解決する方法を考えてみました。

0. コンテナとして使うViewの配置

コンテナとして使うViewは画面(SafeAreaではない)のLeading, Trailing, Bottomとmargin = 0でConstraintを接続して配置します。
この時点で警告が出ますが、Heightは設定しません。

1. コンテナとして使うViewにSafeAreaを表示する

まず、この例の場合だと購入ボタンなどが入っているコンテナViewにSafeArea表示を設定してConstraintを接続できるようにします。

スクリーンショット 2017-10-24 11.49.57.png

2. コンテナとして使っているViewの高さをその中のSubviewに依存させるようにしつつ、最下部のViewはSafeAreaと接続する

コンテナViewの高さがそのSubviewだけで決定できるようにするため、SubviewのHeightとVertical Marginをよしなに設定します。
その時、一番下にあるSubview(例だと購入ボタン)は1.で追加したSafeAreaと接続します。(Constrain to marginsにチェックを入れればSafeAreaと接続されます。) 

これだけです。慣れてしまえば当たり前なのですが、最初なので少し手間取りました。

※追記
TabBarControllerの中に入れるViewControllerの場合、RootのSafeAreaに対して制約を設定するとTabBarの高さが自動的に考慮されますが、RootではないViewの中のSafeAreaに対して制約を設定した場合はTabBarの高さが考慮されないのでメモとして追記します。
TabBarの表示/非表示を自前のアニメーションで切り替えたい場合などは自動的ににTabBarの高さを考慮されると困ることもあるので、Rootではない場所のSafeAreaを使うのが良いかもしれません。