SwiftUI Screen safe area

Viewed 5281

Im trying to calculate the screen safe area size in a SwiftUI app launch so I can derive component sizes from the safe area rectangle for iOS devices of different screen sizes.

UIScreen.main.bounds - I can use this at the start but it gives me the total screen and not the safe area

GeometryReader - using this I can get the CGSize of the safe area but I cant find a way to send this anywhere - tried using Notifications and simple functions both of which caused errors

Finally I tried using the .onPreferenceSet event in the initial view then within that closure set a CGSize variable in a reference file, but doing that, for some reason makes the first view initialise twice. Does anyone know a good way to get the edge insets or the safe area size at app startup?

2 Answers

More simpler solution :

UIApplication.shared.windows.first { $0.isKeyWindow }?.safeAreaInsets.bottom

or shorter:

UIApplication.shared.windows.first?.safeAreaInsets.top

Have you tried this?

You can use EnvironmentObject to send the safe area insets anywhere in your code after initializing it in your initial View.

This works for me.

class GlobalModel: ObservableObject {
    
    //Safe Area size
    @Published var safeArea: (top: CGFloat, bottom: CGFloat)
    
    init() {
        self.safeArea = (0, 0)
    }
}

Inside SceneDelegate.

let globalModel = GlobalModel()
let contentView = ContentView().environmentObject(globalModel)

Inside your initial view.

struct ContentView: View {
    @EnvironmentObject var globalModel: GlobalModel

    var body: some View {
       ZStack {
          GeometryReader { geo in
             Color.clear
                .edgesIgnoringSafeArea(.all)
                .onAppear {
                   self.globalModel.safeArea = (geo.safeAreaInsets.top, geo.safeAreaInsets.bottom)
                }
          }
        
          SomeView()
       }
    }
}

Related