Auto Layoutにおいて制約をsafeAreaLayoutGuideに設定するかどうかの使い分けでSafe Area対応が簡単にできますが、SwiftUIにおいてレイアウトの仕方が完全に変わったため、似たような対応ができなくなりました。

API自体もまだまだ更新されつつけていますが、現時点までのSafe Area対応方法を見てみましょう。

UIKit的な考え方

safeAreaLayoutGuideはありませんが、GeometryReaderによってsafeAreaInsetsを取得することができます。

ではUIKitのように、親の方Safe Areaを無視してレイアウトし、子の方がsafeAreaInsetsと同じスペースを空けばできます。

GeometryReader { proxy.safeAreaInsets
    content
        .padding(proxy.safeAreaInsets)
}
.edgesIgnoringSafeArea(.all)

これができれば、今までの考え方で対応ですますが、iOS 14からSafe Areaを無視したら、safeAreaInsetsがの値が0になりますので、できなくなっています。

食み出し

スペースを空ける方法はできないなら、食み出すようにしてみよう。

GeometryReader { proxy.safeAreaInsets
    content
        .padding(.bottom, proxy.safeAreaInsets.bottom)
        .background(backgroundColor)
        .padding(.bottom, -proxy.safeAreaInsets.bottom)
}

普通にできますが、各方向をマイナスにする必要があるため、ちょっと手間がかかります。

自然的な対応

上記の方法はできるとはいえ、違和感があるますよね。

標準としてドキュメントに書いているわけではありませんが、もっと自然的な対応方法があります。

content
    .background(backgroundColor.edgesIgnoringSafeArea(.all))

直接にcontentの方につけても無視できませんが、background(_:alignment:)経由であればできます。よく考えてみれば、おおよその場合は背景を食み出せば十分で、そのために設計されているかもしれません。

似たようなoverlay(_:alignment:)でもできます。

キーボード

皆さんもキーボードが入力欄などを隠さないようにいろいろ対応してきたと思いますが、このような対応はついに楽になってきました。

なぜかというとiOS 14 beta 3から、キーボードの出入りがSafe Areaを影響するようになりました。そのためignoresSafeArea(_:edges:)も追加されました。

Safe Areaを無視していない限りには対応不要になります。今までのようにキーボードの影響がないSafe Areaが必要な場合、下記のようにできます。

content
    .ignoresSafeArea(.keyboard)

まとめ

  • GeometryReaderを使い、マイナスのpaddingで食み出す
  • background(_:alignment:)経由でignoresSafeArea(_:edges:)

前者の方はちょっとトリッキーですので、特別な必要がなければ後者で対応しましょう。