Search code examples
swiftxcodeswiftui

Why does SwiftUI View background extend into safe area?


Here's a view that navigates to a 2nd view:

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink {
                SecondView()
            } label: {
                Text("Go to 2nd view")
            }
        }
        
    }
}


 struct SecondView: View {
     var body: some View {
         ZStack {
             Color.red
             VStack {
                 Text("This is a test")
                     .background(.green)
                 //Spacer() // <--If you add this, it pushes the Text to the top, but its background no longer respects the safe area--why is this?
             }
         }
     }
 }

On the 2nd screen, the green background of the Text view only extends to its border, which makes sense because the Text is a pull-in view:

enter image description here

Now, if you add Spacer() after the Text(), the Text view pushes to the top of the VStack, which makes sense, but why does its green background suddenly push into the safe area?

In the Apple documentation here, it says:

By default, SwiftUI sizes and positions views to avoid system defined safe areas to ensure that system content or the edges of the device won’t obstruct your views. If your design calls for the background to extend to the screen edges, use the ignoresSafeArea(_:edges:) modifier to override the default.

However, in this case, I'm not using ignoresSafeArea, so why is it acting as if I did, rather than perform the default like Apple says, which is to avoid the safe areas?

enter image description here


Solution

  • You think that you use old background modifier version. But actually, the above code uses a new one, introduced in iOS 15 version of background modifier which by default ignores all safe area edges:

    func background<S>(_ style: S, ignoresSafeAreaEdges edges: Edge.Set = .all) -> some View where S : ShapeStyle
    

    To fix the issue just replace .background(.green) with .background(Color.green) if your app deployment target < iOS 15.0, otherwise use a new modifier: .background { Color.green }.