Dock
Dock

Reputation: 113

SwiftUI: After I dismiss a sheet all buttons inside navigationBarItems do not work anymore

after I dismiss a sheet my buttons on the screen above do not work anymore. Only after pressing on a non-interacting surface the buttons work again. I use swift version 5 and the error occurs in the simulator and on the device.

#Edit

Code Snippets

AddView this will be displayed in a sheet

struct AddView: View {
    @Environment(\.managedObjectContext) var moc
    @Environment(\.presentationMode) var presentationMode

    // some state

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Name")) {
                    TextField("Task-Name (e.g. Eat the 🍰)", text: $title)
                }

                Section(header: Text("Settings")) {
                    DatePicker("Date", selection: $timestamp, displayedComponents: .date)
                    Toggle(isOn: $highPrio) {
                        Text("High Priority")
                    }
                }
            }
            .navigationBarItems(trailing: Button("Add"){
                // logic

                do {
                    try self.moc.save()
                } catch {
                    print(error.localizedDescription)
                }

                self.presentationMode.wrappedValue.dismiss()
            }.alert(isPresented: $showAlert) {
                Alert(title: Text("Name field is empty"), message: Text("Please enter a name"), dismissButton: .default(Text("Got it!")))
            })
            .navigationBarTitle("New Task")
        }
    }
}

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView()
    }
}

ContentView includes a FetchRequest with some functions and nothing more.

struct ContentView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: Task.entity(),
                  sortDescriptors: [
                    NSSortDescriptor(keyPath: \Task.timestamp, ascending: true),
                    NSSortDescriptor(keyPath: \Task.status, ascending: false),
                    NSSortDescriptor(keyPath: \Task.highPriority, ascending: false),
    ]) var tasks: FetchedResults<Task>

    @State private var showingAddSheet = false
    @State private var showAlert = false
    @State private var editMode = false

    var body: some View {
        NavigationView {
            List {
                ForEach(tasks.filter{return self.filterTasks(task: $0)}, id: \.self) { task in
                    HStack {
                        TaskRowView(
                            title: task.wrappedTitle,
                            status: task.wrappedStatus,
                            timestamp: task.wrappedTimestamp,
                            highPriority: task.highPriority,
                            showDetail: self.editMode
                        ).onTapGesture {
                            self.toggleStatus(item: task)
                        }
                    }
                }
                .onDelete(perform: removeTask)

            }
            .navigationBarTitle(self.editMode ? "All Tasks" : "Today")
            .navigationBarItems(leading: Button(self.editMode ? "Done" : "Edit") {self.editMode.toggle()}, trailing: Button("Add") {self.showingAddSheet.toggle()})
            .sheet(isPresented: $showingAddSheet) {
                AddView().environment(\.managedObjectContext, self.moc)
            }
        }.onAppear(perform: {
            self.cleanupTasks()
        }).alert(isPresented: $showAlert) {
            Alert(title: Text("Unfished Task found"),
                  message: Text("Do you want to take over the old tasks or delete them?"),
                  primaryButton: .destructive(Text("Delete all")) {
                    self.removeOldTasks()
                },
                  secondaryButton: .default(Text("Take over")) {
                    self.takeOldTasksOver()
                }
            )
        }
    }

    // functions...
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return ContentView().environment(\.managedObjectContext, context)
    }
}
#endif

Solution

This is a Bug that is related to the .large navigationBarItem. You can set that to .inline to go around it for now:

NavigationView {
    ,,,

    .navigationBarTitle(Text(""), displayMode: .inline)
}

Related Thread: SwiftUI - Navigation bar button not clickable after sheet has been presented

Upvotes: 4

Views: 1866

Answers (2)

FRIDDAY
FRIDDAY

Reputation: 4159

The problem happens when there is a navigationView inside your "AddView" struct. From what I have tested, If you remove the navigationView and just use a button (for dismissal) somewhere else inside the AddView it works perfectly. as below:

var body: some View {
    VStack{
        HStack {
            Spacer()
            Button(action: {
                // logic ..

                self.presentationMode.wrappedValue.dismiss()

            }){
                Text("Add")
            }.alert(isPresented: $showAlert) {
                Alert(title: Text("Name field is empty"), message: Text("Please enter a name"), dismissButton: .default(Text("Got it!")))
            }
            .padding(24)
        }

        Form {
            Section(header: Text("Name")) {
                TextField("Task-Name (e.g. Eat the 🍰)", text: $title)
            }

            Section(header: Text("Settings")) {
                DatePicker("Date", selection: $timestamp, displayedComponents: .date)
                Toggle(isOn: $highPrio) {
                    Text("High Priority")
                }
            }
        }
    }
}

I have this problem in the simulator, but on a real device it works well. Consider updating of xcode, mac OS or iOS.

Upvotes: 1

E.Coms
E.Coms

Reputation: 11531

It's working on device with latest Xcode.

Upvotes: 0

Related Questions