はじめに
この記事は既存、もしくは新規で開発するiOSアプリをiPhoneXに対応するための知見をまとめたものです。
新しい情報やTipsをコメントいただけると随時更新させていただきますので、よろしくお願いします!
iPhoneXについて
- 2017年9月12日に開催されたApple Special Eventにて発表された最新のiPhone
- 顔認証でロック解除ができる「Face ID」を搭載
-
ベゼルレスディスプレイ
- 今までのデバイスと違って、四隅が丸くなっていたり、フロントカメラ部分の凹みがディスプレイに被っていたりするので、このようなディスプレイに対応するためにセーフエリアの概念が新しく追加された
セーフエリアについて
- AppleがiOS11から導入した概念
- ナビゲーションバーやステータスバーなどの外側のUIに被らない安全な領域を取得できる
- 使用するにはXcode9+、iOS11+ SDKが必要
- セーフエリアの領域やマージン幅についてはusagimaruさんの以下の記事がとても参考になる
iPhoneX対応 Tips集
ここからは対応するためのTipsを紹介していきます。
Storyboardでセーフエリアを有効にするには
- 任意のStoryboardを開く
- 右側にあるInterface Builderのインスペクタを開く
- 「Use Safe Area Layout Guides」のチェックをONにする
- セーフエリア(UILayoutGuide) が追加される
- セーフエリアを有効にしていなかったStoryboardでセーフエリアを有効にすると、Top Layout GuideやBottom Layout Guideに接続していたビューは自動でセーフエリアのTop、Bottomに差し替えてくれる
ソースコード上からセーフエリアを取得したい
- iOS11からは上記のStoryboardでセーフエリアを有効にしたときに追加されるUILayoutGuideがUIViewのプロパティに safeAreaLayoutGuide (UILayoutGuide) として追加されている
- iOS11からはUIViewのプロパティに safeAreaInsets (UIEdgeInsets) が追加されていて、そこからセーフエリアのマージンを取得できる
- iOS11+しか使えないプロパティのため、 #available(iOS 11, *) での分岐が必要
- 以下のhituziandoさんの記事によると、UIViewControllerのライフサイクルで一番最初にsafeAreaInsetsが確定するのはviewWillLayoutSubviews
ViewController.swift
import UIKit
class ViewController: UIViewController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// iOS11かどうかで分岐する
let safeAreaInsets: UIEdgeInsets
if #available(iOS 11, *) {
safeAreaInsets = view.safeAreaInsets
} else {
safeAreaInsets = .zero
}
print("safeAreaInsets: \(safeAreaInsets)")
}
}
ソースコード上からセーフエリアの変化を感知したい
- iOS11からはセーフエリアの変化を感知するためにUIViewに open func safeAreaInsetsDidChange() が、UIViewControllerに open func viewSafeAreaInsetsDidChange() が追加されている
- それぞれ、オーバーライドすることで、メソッド内でセーフエリアの変化を感知できる
- このメソッドを便利に使えるようにする拡張方法などはmarty-suzukiさんの以下の記事が参考になる
セーフエリアだけで切り取るだけのデザインは非推奨
- 上下に常に黒いバーが存在するような、セーフエリアで切り取るだけのデザインのアプリはAppleが提供する標準アプリと矛盾したデザインになってしまうため、非推奨となっている
- 以下の画像のように、上下の背景とコンテンツが溶け込むような意識をする必要がある
必要な箇所でclipsToBoundsがtrueになっているかを注意する
- 今までのデバイスだと、ディスプレイの外に配置しておけば見えなくなるので、安心して画面外に置いていたビューが、セーフエリアによってあられもない姿にされてしまう
- 見切れさせたくない箇所は、しっかりとclipsToBoundsをtrueにしておく必要がある
コンテンツをフルスクリーン表示する際にはアスペクト比を保つ
- iPhoneXでコンテンツをフルスクリーンで表示する際には、iPhone8を基準にした場合、左右を切り取って上下を埋めて表示するか、左右を合わせて上下を凹ませて表示するかして、アスペクト比は保つようにする必要がある
iPhoneXの下のバーを消したい
- バーの正式名称はHome Indicator
- iOS11からはHome Indicatorを非表示にするためのメソッド(
open func prefersHomeIndicatorAutoHidden() -> Bool
)がUIViewControllerに追加されている- オーバーライドしてtrueを返せば、Home Indicatorは画面に一定時間触らなければ、自動的に非表示になる
- 非表示になってから画面に触れると、Home Indocatorはすぐに表示される
- Home Indicatorは基本表示されていないとユーザーに混乱を招くため、画像や動画をフルスクリーン表示する際など、Home Indocatorが被ることでコンテンツの表示に影響が出てしまう場合以外は非表示にしないようにする
ViewController.swift
import UIKit
class ViewController: UIViewController {
private var isHiddenHomeIndicator: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 11, *) {
// HomeIndicatorの表示を更新するためのメソッド
setNeedsUpdateOfHomeIndicatorAutoHidden()
}
}
@available(iOS 11, *)
override func prefersHomeIndicatorAutoHidden() -> Bool {
return isHiddenHomeIndicator
}
}
セーフエリアに対応済みのレイアウト系ライブラリ一覧
- robb/Cartography
-
marty-suzuki/MisterFusion
- 開発者本人のコミットが反映されたver.
3.1.0
からサポートされている
- 開発者本人のコミットが反映されたver.
-
SnapKit/SnapKit
- 公式ドキュメントにて、safeAreaLayoutGuideへの対応方法が追加されている