How to dismiss fullScreenCover in SwiftUI

⋅ 3 min read ⋅ SwiftUI

Table of Contents

A modal presentation (fullScreenCover) is one of the core presentations in iOS. SwiftUI has many ways to dismiss a modal view based on how you structure your view and the minimum iOS version you support.

There are three ways to dismiss a modal in SwiftUI.

  1. Dismiss a modal in the same view.
  2. Dismiss a modal with @Binding.
  3. Dismiss a modal with @Environment.

How to dismiss modal in the same view

If a modal view sits in the same view that presenting it, we can easily dismiss the modal view by controlling the same binding value (isPresented) since it has access to the binding.

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

var body: some View {
Button("Detail") {
isPresented = true
}
.fullScreenCover(isPresented: $isPresented) {
// Detail View
Button("Back to Main") {
isPresented = false
}
}
}
}

The detail view Button("Back to Main") can reach isPresented. So, we can easily dismiss it by setting isPresented to false to dismiss the modal.

Set isPresented to false to dismiss a modal.
Set isPresented to false to dismiss a modal.

Most of the time, the view that you want to present might be too complicated to fit within a fullScreenCover closure. So, you probably separate it into another file.

Here we create a new DetailView that we want to present.

struct DetailView: View {
var body: some View {
Button("Back to Main") {

}
}
}

With a separate view like this, we no longer have access to the isPresented binding.

You have two ways to dismiss a modal view that isn't on the same view.

  1. Dismiss a modal with @Binding.
  2. Dismiss a modal with @Environment.

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.

How to dismiss modal with @Binding

One way to dismiss a presented view is to pass the isPresented binding to that view.

In this example, we add an isPresented binding to the DetailView.

struct DetailView: View {
// 1
@Binding var isPresented: Bool

var body: some View {
Button("Back to Main") {
// 2
isPresented = false
}
}
}

1 The DetailView accept the isPresented binding value.
2 Then, we use it to dismiss the modal.

To use it, we pass an isPresented binding from the presenting view to a modal view.

struct ContentView: View {
// 1
@State private var isPresented = false

var body: some View {
Button("Detail") {
isPresented = true
}
.fullScreenCover(isPresented: $isPresented) {
// 2
DetailView(isPresented: $isPresented)
}
}
}

We pass down isPresented 1 from the presenting view to presented view, DetailView 2.

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.

Dismiss a modal with @Environment

The other way for the view to dismiss itself is using environment value via the @Environment property wrapper.

Which environment value to use is depends on the iOS version you supported.

How to dismiss modal in iOS 13/14

For a view to dismissing itself, we have to add @Environment(\.presentationMode) var presentationMode to a presented view.

We can dismiss the view by calling presentationMode.wrappedValue.dismiss().

struct DetailView: View {
@Environment(\.presentationMode) var presentationMode

var body: some View {
Button("Back to Main") {
presentationMode.wrappedValue.dismiss()
}
}
}

Then we can use DetailView as a modal view without passing anything.

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

var body: some View {
Button("Detail") {
isPresented = true
}
.fullScreenCover(isPresented: $isPresented) {
DetailView()
}
}
}

How to dismiss modal in iOS 15

In iOS 15, Apple deprecated the presentationMode environment value, replacing it with a dismiss action (dismiss).

For a view to dismissing itself, we have to add @Environment(\.dismiss) private var dismiss to a presented view.

We can dismiss the view by calling dismiss().

struct DetailView: View {
@Environment(\.dismiss) var dismiss

var body: some View {
Button("Back to Main") {
dismiss()
}
}
}

Then we can use DetailView as a modal view without passing anything.

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

var body: some View {
Button("Detail") {
isPresented = true
}
.fullScreenCover(isPresented: $isPresented) {
DetailView()
}
}
}

Read more article about SwiftUI or see all available topic

Enjoy the read?

If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.

Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.

If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.

Become a patron Buy me a coffee Tweet Share
Previous
How to use custom fonts with SwiftUI

Learn how to use a custom font in your SwiftUI app.

Next
Create SwiftUI List from an Array

It is very common to populate a list view from an array of data. Let's learn how to do it in SwiftUI.

← Home