How to access safe area size in SwiftUI?

You can use a GeometryReader to access the safe area.
See: https://developer.apple.com/documentation/swiftui/geometryreader.

struct ContentView : View {
    
    var body: some View {
        GeometryReader { geometry in
            VStack {
                Spacer()
                Color.red
                    .frame(
                        width: geometry.size.width,
                        height: geometry.safeAreaInsets.top,
                        alignment: .center
                )
                    .aspectRatio(contentMode: ContentMode.fit)
            }
        }
        .edgesIgnoringSafeArea(.bottom)
    }
}

But FYI: The safe area is not a size. It is an EdgeInsets.


If you use edgesIgnoringSafeArea on an parentView and you want to access the device UISafeAreaInsets you can do the following:

Code

private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets {
        (UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.safeAreaInsets ?? .zero).insets
    }
}

extension EnvironmentValues {
    
    var safeAreaInsets: EdgeInsets {
        self[SafeAreaInsetsKey.self]
    }
}

private extension UIEdgeInsets {
    
    var insets: EdgeInsets {
        EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
    }
}

Usage

struct MyView: View {
    
    @Environment(\.safeAreaInsets) private var safeAreaInsets
    
    var body: some View {
        Text("Ciao")
            .padding(safeAreaInsets)
    }
}

UIApplication.shared.windows is deprecated, you can now use connectedScenes:

import SwiftUI

extension UIApplication {
    var keyWindow: UIWindow? {
        connectedScenes
            .compactMap {
                $0 as? UIWindowScene
            }
            .flatMap {
                $0.windows
            }
            .first {
                $0.isKeyWindow
            }
    }
}

private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets {
        UIApplication.shared.keyWindow?.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)
    }
}

And then use Environment property in your View to get safe area insets:

@Environment(\.safeAreaInsets) private var safeAreaInsets

Tags:

Swiftui