Sheets in SwiftUI Explained

Tutorial — How to show and dismiss sheets in SwiftUI

Ix76y
4 min readFeb 16, 2023

--

With iOS 13 Apple introduced sheets — a modal view that can be used to show additional content to the user without fully navigation away from the original view.

In this tutorial I will explain how you can create sheets and dismiss them.

Prerequisites

  • Mac with Xcode 14+ installed and iOS 13+ or macOS 10.15+
  • Experience in Swift programming advantageous but not necessary

Setup

To get started you can either create a new XCode Project or use an existing one. Sheets work for both iOS and macOS apps and are just displayed slightly differently on the different platforms.

When creating a new project make sure you have SwiftUI as the interface and not the older Storyboard. If you don’t know how to create a project in XCode you can follow the start of this story, where I explain the it step-by-step: https://medium.com/@ix76y/creating-a-image-card-in-swift-ui-beginner-tutorial-2881b4420ea3.

Presenting a Sheet

A sheet is build with three things:

  • isPresented: a boolean binding variable defining if the sheet is shown or not
  • onDismiss: an action that should be executed when the sheet is being dismissed
  • content: the actual content displayed in the sheet

More Information: Apple Developer Documentation.

Let’s start with creating a boolean binding variable to keep track of the sheets state. Add the following line inside your ContentView struct but before the view body.

@State private var isShowingSheet = false

Perfect, now we already have the first component for our sheet. Next we need a Button or something the user can click to open the sheet. To add a button:

  1. Remove everything inside the view body
  2. Use the component Library to drag and drop a Button into the view or just write the code
  3. Change the label of the button
  4. Add an action to the button to toggle isShowingSheet on click

The result should look like this:

struct ContentView: View {
@State private var isShowingSheet = false

var body: some View {
Button("Show More Information") {
isShowingSheet.toggle() // toggle isShowingSheet on button click
}
}
}

Dismiss Function

The second argument for our sheet is a function we want to be called when the sheet is getting dismissed. For now we can just declare a simple function inside the ContentView that prints that the sheet was dismissed, but you may want to add some further logic later on.

struct ContentView: View {
@State private var isShowingSheet = false

var body: some View {
Button("Show More Information") {
isShowingSheet.toggle()
}
}

func didDismiss() {
print("User dismissed the sheet.")
}
}

Sheet Content

Finally the only thing left is the actual sheet content and putting it all together. For the sheet content you can use a complete separate view or just build a new view the way you want it.

For this example we will just go with a little text. Add the sheet to the button and pass the first two arguments isPresented and onDismiss. Then inside the curly braces add the actual content of the sheet. In this example I went with two text components inside a VStack to sort them vertical.

struct ContentView: View {
@State private var isShowingSheet = false

var body: some View {
Button("Show More Information") {
isShowingSheet.toggle()
}.sheet(isPresented: $isShowingSheet, onDismiss: didDismiss) {
VStack {
Text("SwiftUI Tutorial")
.font(.title)
.padding(32)
Text("Showing sheets in SwiftUI is super easy.")
.padding(16)
}
}
}

func didDismiss() {
print("User dismissed the sheet.")
}
}

Note: You may have noticed the $ in front of isShowingSheet when passing it to the sheet. This allows us to bind the sheet to the value. This way, whenever isShowingSheet is changed the sheet will be updated too.

Resume the XCode preview or start a simulator and you can click the button to show the sheet. If you pull the sheet down it will automatically dismiss it and you will be able to see the original view again.

Dismissing the Sheet

While a user can always pull a sheet down to dismiss it we can also add a button to dismiss it. This button will work the same way as the original button to show the view and just toggle the state of the sheet.

To do so we can extend the content of the sheet and adding a button to the bottom of the VStack that will allow us to dismiss the sheet.

struct ContentView: View {
@State private var isShowingSheet = false

var body: some View {
Button("Show More Information") {
isShowingSheet.toggle()
}.sheet(isPresented: $isShowingSheet, onDismiss: didDismiss) {
VStack {
Text("SwiftUI Tutorial")
.font(.title)
.padding(32)
Text("Showing sheets in SwiftUI is super easy.")
.padding(16)
Button("Dismiss", action: { isShowingSheet.toggle() })
}
}
}

func didDismiss() {
print("User dismissed the sheet.")
}
}

Now we can run the code again and we will have a new button on the sheet that allows us to dismiss the sheet in a second way.

Showing and dismissing sheets in XCode with example code.
Showing and Dismissing Sheets

Thank You! ❤️

You should now be able to create sheets in your SwiftUI app. I hope you enjoyed reading this tutorial and found it helpful! 👍

If you did enjoy this story please follow me for more stories! 😊

--

--

Ix76y

Hi my name is Izzy. I love to write code, currently my favorits are Python, Swift, Rust & C and I enjoy writing tutorials about all sorts of things 😊.