A sheet is a specific type of modal presentation that is commonly used in SwiftUI. It’s a way to present a secondary view in a card-like manner, sliding it up from the bottom of the screen.
Sheets are useful for presenting additional information, settings, or actions without fully obscuring the underlying content. They are typically dismissed by dragging them downwards or by using a dismiss button within the sheet.
To dismiss a sheet programmatically, you can pass an @Binding
variable to control the presentation state, or use an environment value of type DismissAction
.
DismissAction is a new environment value introduced in iOS 15 and macOS 12 that provides an action to dismiss the current presentation. It can be used to dismiss sheets, popovers, navigation views, and windows.
The dismiss
environment value can be called as a function because it stores a DismissAction instance, which defines a callAsFunction()
method. This method is called implicitly when you write dismiss()
, and it performs the appropriate dismissal action depending on the context.
If you use the dismiss
environment value inside a sheet, it will dismiss the sheet. If you use it inside a navigation view, it will pop the current view from the navigation stack.
struct ContentView: View {
@State private var showingSheet = false
var body: some View {
Button("Show Sheet") {
showingSheet = true
}
.sheet(isPresented: $showingSheet) {
SheetView()
}
}
}
struct SheetView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
Button("Dismiss Sheet") {
dismiss()
}
}
}
The @Binding
property creates a shared reference, allowing multiple views to access and modify the same value. This creates a two-way connection between the views, allowing the presented view to modify the binding and dismiss itself.
struct ContentView: View {
@State private var showDetailView = false
var body: some View {
Button("Show Detail View") {
showDetailView = true
}
.sheet(isPresented: $showDetailView) {
DetailView(isPresented: $showDetailView)
}
}
}
struct DetailView: View {
@Binding var isPresented: Bool
var body: some View {
Button("Dismiss") {
isPresented = false // Modifying the binding dismisses the view
}
}
}
In this example, we create a @State
property named showDetailView
to control the presentation of the sheet. The .sheet()
modifier uses the isPresented
binding to determine whether or not to show the sheet. We pass the isPresented
binding to the DetailView using $showDetailView
.
Deprecated since iOS 15
PresentationMode is a environment value that indicates whether a view is currently presented by another view, such as a sheet or a navigation view. It also provides a wrappedValue property that can be used to dismiss the view programmatically.
The main difference between PresentationMode and DismissAction is that the former is a binding to the current presentation state, while the latter is a function that performs the dismissal. DismissAction is also more versatile, as it can be used to dismiss sheets, popovers, navigation views, and windows. PresentationMode only works for sheets and navigation views.
struct ContentView: View {
@State private var isModalPresented = false
var body: some View {
Button("Show Modal") {
isModalPresented = true
}
.sheet(isPresented: $isModalPresented) {
ModalView()
}
}
}
struct ModalView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("This is the modal view!")
Button("Dismiss") {
presentationMode.wrappedValue.dismiss()
}
}
}
}