DEV Community

James Creston
James Creston

Posted on

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

Top comments (4)

Collapse
 
yowise profile image
a.infosecflavour

Hey, great post!
It will help a lot if you would format the first half of the code too! 🙌

Collapse
 
creston profile image
James Creston

Thank you for the feed back, let me try again and let me know if it’s corrected.

Collapse
 
yowise profile image
a.infosecflavour

great

Thread Thread
 
creston profile image
James Creston

Thank you for the help, now I just need someone to assist with the bug in my code. Lol