I am looking for a pure SwiftUI based solution to determine whether the iOS device has top notch based on the safe area insets of the root view. While this is easy to determine in UIKit, for SwiftUI the only solution that I have found so far is also UIKittish, that is:
extension UIApplication {
var currentWindow: UIWindow? {
connectedScenes
.compactMap {
$0 as? UIWindowScene
}
.flatMap {
$0.windows
}
.first {
$0.isKeyWindow
}
}
}
private struct SafeAreaInsetsKey: EnvironmentKey {
static var defaultValue: EdgeInsets {
UIApplication.shared.currentWindow?.safeAreaInsets.swiftUiInsets ?? EdgeInsets()
}
}
extension EnvironmentValues {
var safeAreaInsets: EdgeInsets {
self[SafeAreaInsetsKey.self]
}
}
private extension UIEdgeInsets {
var swiftUiInsets: EdgeInsets {
EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
}
}
While it's likely that SwiftUI will continue to use UIKit elements such as UIWindow under the hood so the solution above will continue to work for next several years, I still want to know if there is a pure SwiftUI based solution to this.
You can get safe area insets from a
GeometryReader. You can put aGeometryReaderat the very top of the view hierarchy, perhaps directly inWindowGroup { ... }. Then you can send the insets down with an environment key.Note that you need to preview the whole
GeometryReaderfor this to work in Xcode Previews. You can encapsulate the geometry reader andZStackinto a view modifier like this, so that you can conveniently use it in Previews: