153
102

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOS 11 の Safe Area は Auto Layout だけでなくコードベースでも取れる

Last updated at Posted at 2017-09-13

iOS 11 では Safe Area という概念を導入しました。そして本日のイベントをご覧になられた方、もしくは iPhone X を少しでも掘ってみた方ならわかると思いますが、この Safe Area の概念はレイアウトする時、特に iPhone X ではものすごい重要になってきます。

具体的に iPhone X 向けのレイアウト最適化の話については是非とも公式の Building Apps for iPhone XDesigning for iPhone X をご覧いただければと思いますが、ここではとりあえず筆者みたいな Auto Layout 死んでも使わない人()向けに「Safe Area」をコードで取る方法を簡単に説明したいと思います。(ちなみに Auto Layout でしたら safeAreaLayoutGuide を使うことができます)

iOS 11 からは UIView では safeAreaInsets という UIEdgeInsets 型のプロパティーが追加されました。公式の説明によりますとこれは get-only のプロパティーで、ビューヒエラルキーに依存しているとのことです。なので最終的には Status Bar や TabBar の他に、ビューヒエラルキーに入っている UIViewControlleradditionalSafeAreaInsets にも依存しています。

例えばルート ViewController が保持している view ParentView は、iPhone X の縦画面なら上に 44、下に 34 ピクセルの Safe Area がこの safeAreaInsets プロパティーで読み取れます(UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0))。そしてこの ParentView だけでなく、ParentView に追加した子ビュー ChildView も、ChildView 自分自身の frame に応じて、適切な safeAreaInsets が読み取れます。例えば ChildView の frame.origin.y10 なら、ChildView の safeAreaInsets.top44 - 10 = 34 になります。また、さらにこの ChildView に追加した子ビュー、つまり ParentView から見た GrandChildView でも、ビューヒエラルキーに則って ParentView から見た領域で safeAreaInsets を適切に読み取れます。例えば GrandChildView 自身の frame.origin.y10 なら、これは ChildView から見た 10 なので、さらに ChildView の 10 を合計した 20 こそが ParentView から見た frame.origin.y になります。ですので GrandChildView の中に残っている safeAreaInsets.top44 - 20 = 24 にならなければなりません。そして実際 GrandChildView の safeAreaInsets.top を確認してみれば確かにこれが 24 になります。

ただし、注意点としては、まだビューヒエラルキーに追加されていない場合(つまり superviewnil か、superview を遡ると最終的に nil になる場合)、safeAreaInsets.zero になります。

ちなみに、GitHub に簡単なサンプルプロジェクトを上げました。iPhone X のシミュレーターで起動すると下記のようなスクリーンショットになります。この時裏から青、赤、緑のビューのそれぞれの safeAreaInsets をコンソールで確認できます(筆者の環境の出力も下記に置いておきます)

スクリーンショット 2017-09-13 15.35.27.png
self: UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
sub: UIEdgeInsets(top: 34.0, left: 0.0, bottom: 24.0, right: 0.0)
grand: UIEdgeInsets(top: 24.0, left: 0.0, bottom: 14.0, right: 0.0)

(上記の出力について、self は一番裏にある青のビュー、sub は一個上にある赤のビュー、そして grand は一番上にある緑のビューを指します)

余談ですが、当然 NotAutoLayout もこの機能には対応する予定です。

153
102
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
153
102

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?