SwiftUI .toolbar not showing at bottom of screen

creston

James Creston

Posted on June 7, 2024

SwiftUI .toolbar not showing at bottom of screen

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)
    }
}


Enter fullscreen mode Exit fullscreen mode

`
Image description
Image description

💖 💪 🙅 🚩
creston
James Creston

Posted on June 7, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related