4

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

Dock
  • 103
  • 7
  • Are you using a device not simulator? – E.Coms Jan 11 '20 at 17:13
  • The error has occurred in both of them (simulator and on the device) – Dock Jan 11 '20 at 17:25
  • I have created `.navigationBarItems` with buttons and it works perfectly. It seems something inside the struct's body effects the buttons. You have to provide the structs' body or more code in your question to solve the problem. – FRIDDAY Jan 11 '20 at 17:52
  • All right I have added code snippets to the thread. I shortened it a bit for readability. – Dock Jan 11 '20 at 18:17
  • 2
    It's a bug. Answered here: https://stackoverflow.com/questions/58512344/swiftui-navigation-bar-button-not-clickable-after-sheet-has-been-presented – Russ Neufeld Jan 12 '20 at 02:43

2 Answers2

1

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.

FRIDDAY
  • 3,781
  • 1
  • 29
  • 43
  • Unfortunately, the error still occurs. ``` OS Catalina V. 10.15.2 (19C57) XCode V. 11.3 (11C29) iPhone X V 13.3 ``` But with Russ Neufeld answer it worked. – Dock Jan 12 '20 at 08:40
0

It's working on device with latest Xcode.

E.Coms
  • 11,065
  • 2
  • 23
  • 35