I’m attempting to dismiss the detail view in a master detail view on an iPad (e.g. if that item is deleted in the master view and needs to blank out the right hand side).
import SwiftUI
struct ContentView: View {
@State var selection: String?
var body: some View {
NavigationView {
List {
NavigationLink(tag: "item1", selection: $selection) {
DetailView(item: "Item 1", selection: $selection)
} label: {
Text("Item 1")
}
NavigationLink(tag: "item2", selection: $selection) {
DetailView(item: "Item 2", selection: $selection)
} label: {
Text("Item 2")
}
NavigationLink(tag: "item3", selection: $selection) {
DetailView(item: "Item 3", selection: $selection)
} label: {
Text("Item 3")
}
}
Text("Blank View")
}
}
}
struct DetailView: View {
let item: String
@Binding var selection: String?
@Environment(.dismiss) var dismiss
var body: some View {
VStack {
Text("Detail for (item)")
Button {
selection = nil
// dismiss()
} label: {
Text("Dismiss")
}
}
}
}
This is an example that demonstrates the issue. When dismiss is pressed it nils the selection which on iPhone dismisses the detail controller. On the iPad it keeps the detail view there, rather than returning to the blank view.
Here is the view before selecting an item. You can see the blank view on the right hand side.
After selecting an item the left hand side is selected, and the right hand side shows the appropriate detail view.
After dismissing the view by nilling the selection (or using the environment dismiss) the selection on the left disappears as it should, but the detail view on the right stays put. This should have disappeared and the blank view should show again.
2
Answers
I have worked out a solution that works however it requires some extra logic. It needs some sort of check to see if the data is there and if it isn't then conditionally show the main view or a blank view.
Here is the modified
DetailView
for the example I used in my question. If the selection binding is nil then display the blank view again.In the case of an
NSManagedObject
you can checkobject.managedObjectContext != nil
. I decided to make this an extension to make this easier.Which is used like this:
If you’re willing to give up the
splitView
(having the items on that sidebar), you can override the default navigation settings to make it behave as it would on an iPhone (using stacked navigation views), then the dismiss button works just fine. Add this modifier.navigationViewStyle(StackNavigationViewStyle())
toNavigationView
: