SwiftUI .toolbar not showing at bottom of screen
Tags: help
Published: 2024-06-07 12:23:43

Hello, new coder here learning SwiftUI for the first time. Started an iOS coding journey this year after having not coded since 2005 when I last coded a social media website using html, css, and cold fusion7. 

I have been following tutorials for a while and just cannot get past this bug that doesn’t generate any errors. 

I may have my .toolbar embedded is the wrong area of my View Controller. 

But my tool bar refuses to show at the bottom of the screen. 

See the two screen shots. One shows the toolbar but the report title and select button are not at the stop of the screen. 

The other is where I fixed the select/edit button but now the toolbar is missing. 

```

import SwiftUI
import PhotosUI

struct ReportDetailView: View {
    @Binding var report: Report
    @State private var showPhotoLibrary = false
    @State private var showCamera = false
    @State private var selectedImages: [UIImage] = []
    @State private var selectedImage: UIImage?
    @State private var selectedImageIndex: Int?
    @State private var showEditCaption = false
    @State private var showEmailSheet = false
    @State private var isSelecting = false
    @State private var selectedPhotos = Set<Int>()

    var body: some View {
        VStack {
            TextField("Report Title", text: Binding(
                get: { report.title ?? "" },
                set: { report.title = $0 }
            ))
            .font(.largeTitle)
            .padding(.top)
            .background(Color.clear)
            .frame(maxWidth: .infinity, alignment: .leading)
            .textInputAutocapitalization(.words)
            .onTapGesture {
                self.dismissKeyboard()
            }
            .padding(.horizontal)

            if report.photos.isEmpty {
                Text("No Photos")
                    .foregroundColor(.gray)
                    .padding()
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
            } else {
                ScrollView {
                    LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))]) {
                        ForEach(report.photos.indices, id: \.self) { index in
                            VStack {
                                if let photo = report.photos[index].image {
                                    Image(uiImage: photo)
                                        .resizable()
                                        .aspectRatio(contentMode: .fit)
                                        .onTapGesture {
                                            if isSelecting {
                                                if selectedPhotos.contains(index) {
                                                    selectedPhotos.remove(index)
                                                } else {
                                                    selectedPhotos.insert(index)
                                                }
                                            } else {
                                                selectedImage = report.photos[index].image
                                                selectedImageIndex = index
                                                showEditCaption = true
                                            }
                                        }
                                        .overlay(
                                            isSelecting ?
                                            Circle()
                                                .stroke(selectedPhotos.contains(index) ? Color.blue : Color.clear, lineWidth: 3)
                                                .frame(width: 30, height: 30)
                                                .padding(5)
                                                .background(Color.white.opacity(0.7).clipShape(Circle()))
                                                .padding()
                                            : nil
                                        )
                                }
                                Text(report.photos[index].caption)
                                    .font(.caption)
                            }
                        }
                    }
                }
            }
        }
        .navigationBarItems(trailing: Button(action: {
            isSelecting.toggle()
            selectedPhotos.removeAll()
        }) {
            Text(isSelecting ? "Cancel" : "Edit")
        })
        .toolbar {
            ToolbarItem(placement: .bottomBar) {
                HStack {
                    if isSelecting {
                        Button(action: deleteSelectedPhotos) {
                            Image(systemName: "trash")
                                .foregroundColor(.red)
                        }
                        Spacer()
                    }
                    
                    Button(action: { showPhotoLibrary = true }) {
                        Image(systemName: "photo.on.rectangle.angled")
                    }
                    Spacer()
                    Button(action: { showCamera = true }) {
                        Image(systemName: "camera")
                    }
                    Spacer()
                    Button(action: { showEmailSheet = true }) {
                        Image(systemName: "envelope")
                    }
                }
            }
        }
        .sheet(isPresented: $showPhotoLibrary) {
            UnifiedPicker(pickerType: .photoLibrary(single: false), selectedImages: $selectedImages)
                .onDisappear {
                    for image in selectedImages {
                        if let imageData = image.jpegData(compressionQuality: 1.0) {
                            report.photos.append(Photo(imageData: imageData, caption: ""))
                        }
                    }
                    selectedImages.removeAll()
                }
        }
        .sheet(isPresented: $showCamera) {
            UnifiedPicker(pickerType: .camera, selectedImages: $selectedImages)
                .onDisappear {
                    if let image = selectedImages.first, let imageData = image.jpegData(compressionQuality: 1.0) {
                        report.photos.append(Photo(imageData: imageData, caption: ""))
                    }
                    selectedImages.removeAll()
                }
        }
        .sheet(isPresented: $showEditCaption) {
            if let selectedIndex = selectedImageIndex {
                EditCaptionView(photo: $report.photos[selectedIndex])
            }
        }
        .sheet(isPresented: $showEmailSheet) {
            if let emailData = emailData {
                MailComposeViewController(mailData: emailData)
            }
        }
    }

    private func deleteSelectedPhotos() {
        for index in selectedPhotos.sorted(by: >) {
            report.photos.remove(at: index)
        }
        selectedPhotos.removeAll()
        isSelecting.toggle()
    }

    private func dismissKeyboard() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }

    private var emailData: Data? {
        return PDFGenerator.generatePDF(for: report)
    }
}

struct ReportDetailView_Previews: PreviewProvider {
    @State static var report = Report(title: "Sample Report", date: Date(), photos: [])
    static var previews: some View {
        ReportDetailView(report: $report)
    }
}
```
`
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i22io6l8u53zxtlz6x9.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bi6ki7yl5el23e6wfuxv.png)