SwiftUI VStack spacing: not working properly

Viewed 1110

I have a SwiftUI VStack that sits inside a scrollView, a Geometry reader and a NavigationView, here is the code:

struct RezeptList: View {

    @Environment(\.colorScheme) var colorScheme: ColorScheme
    @EnvironmentObject private var recipeStore: RecipeStore

    @State private var searching = false
    @State private var searchText = ""
    @State private var showingAddRecipeView = false

    var body: some View {
        NavigationView{
            GeometryReader { geo in
                ScrollView {
                    SearchBar(searchText: self.$searchText, isSearching: self.$searching)
                    VStack(spacing: 30) {

                        ForEach(self.recipeStore.recipes.filter{$0.name.hasPrefix(self.searchText) || self.searchText == ""}) {recipe in
                            NavigationLink(destination:
                            RezeptDetail(recipe: recipe).environmentObject(self.recipeStore)) {
                                Card(rezept: recipe,width: geo.size.width - 20)
                            }
                            .buttonStyle(PlainButtonStyle())
                        }

                        .navigationBarItems(trailing: Button(action: {
                            self.showingAddRecipeView = true
                        }){
                            Image(systemName: "square.and.pencil")
                                .foregroundColor(.primary)
                            }
                        .padding()
                        )
                    }
                    .padding(.bottom)
                    .navigationBarTitle("Rezepte")
                    .sheet(isPresented: self.$showingAddRecipeView) {
                        AddRecipeView(isPresented: self.$showingAddRecipeView)
                            .environmentObject(self.recipeStore)
                    }
                }
            }
        }
    }

    init() {
        UINavigationBar.appearance().tintColor = UIColor.label
    }

}

But it looks like this no matter the amount of spacing: Image

But I noticed when I move the .navigationBarItems modifiers it works but then as soon as you tap on the navigationLink the app crashes.

1 Answers

SwiftUI sometimes has weird behavior issues with the placement of some modifiers.

In your case, if you move .navigationBarItems to after navigationBarTitle, it should fix this issue and you will get back your VStack spacing.

.navigationBarTitle("Rezepte")
.navigationBarItems(trailing: Button(action: {
    self.showingAddRecipeView = true
}, label: {
    Image(systemName: "square.and.pencil")
        .foregroundColor(.primary)
}).padding())

Besides, I have observed that it's better to have these navigation related modifiers closer to the NavigationView than deep within the hierarchy.


Example (based on your view hierarchy):

struct ContentView: View {
    @State var isShowing: Bool = false
    
    var body: some View {
        NavigationView {
            GeometryReader { (geo) in
                ScrollView {
                    VStack(spacing: 60) {
                        ForEach(0...10, id:\.self) { (index) in
                            NavigationLink(destination: Text(String(index))) {
                                Text("Button")
                            }
                        }
                    }
                    .navigationBarTitle("Title")
                    .navigationBarItems(trailing: Button(action: {
                        self.isShowing = true
                    }, label: {
                        Image(systemName: "square.and.pencil")
                    }))
                    .sheet(isPresented: self.$isShowing) {
                        Button(action: {
                            self.isShowing = false
                        }) {
                            Text("Dismiss")
                        }
                    }
                }
            }
        }
    }
}
Related