Clean Up Your Sheet API

Chase
3 min readMar 24, 2025

If you are like most developers, you probably have more parameters than are required to get a working sheet in SwiftUI. Please pardon the potty humor and let’s work together and get that API cleaned up.

an image of a poop emoji standing in front of a sheet
Generated by the Image Playgrounds app

Before we get started, please take a couple of seconds to follow me and 👏 clap for the article so that we can help more people learn about this useful content.

Most Sheet APIs

Many developers (including myself) have writing code that is similar to the following. In this example, we are passing a binding to the sheet. Once in the sheet view, we are using that binding to close the sheet. There isn’t really much wrong with this implementation except that our sheet view has an unnecessarily long API, and it would probably be worse if this was more than a quick tutorial. So what do we do to fix it?

//  ContentView.swift
import SwiftUI

struct ContentView: View {
@State var isShowingMyCustomSheet = false

var body: some View {
VStack {
Button("Toggle the Sheet") {
isShowingMyCustomSheet.toggle()
}
}
.padding()
.sheet(isPresented: $isShowingMyCustomSheet) {
// our long sheet API
MySheetView(isShowingMyCustomSheet: $isShowingMyCustomSheet)
}
}
}

struct MySheetView: View {
@Binding var isShowingMyCustomSheet: Bool

var body: some View {
VStack {
HStack {
Spacer()
Button {
isShowingMyCustomSheet.toggle()
} label: {
Image(systemName: "xmark")
}
}.padding()

Spacer()
// If you want this image for your project, you can save the title
// image from this article to your project file
Image(.poopEmojiCharacter)
.resizable()
.scaledToFit()
Spacer()
}
}
}

#Preview {
ContentView()
}

Environment variables for the win

In this cleaned up version of the sheet view, we swapped the Binding to the parents state variable with an environment variable. This environment variable is meant to dismiss any view. The dismiss environment variable works with sheets and NavigationStacks, and is a great tool to have in your developer toolbelt.

//  ContentView.swift
import SwiftUI

struct ContentView: View {
@State var isShowingMyCustomSheet = false

var body: some View {
VStack {
Button("Toggle the Sheet") {
isShowingMyCustomSheet.toggle()
}
}
.padding()
.sheet(isPresented: $isShowingMyCustomSheet) {
// Our short sheet API
MySheetView()
}
}
}

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

var body: some View {
VStack {
HStack {
Spacer()
Button {
dismiss()
} label: {
Image(systemName: "xmark")
}
}.padding()

Spacer()
// If you want this image for your project, you can save the title
// image from this article to your project file
Image(.poopEmojiCharacter)
.resizable()
.scaledToFit()
Spacer()
}
}
}

#Preview {
ContentView()
}

If you got value from this article, please consider following me, 👏 clapping for this article, or sharing it to help others more easily find it.

If you have any questions on the topic or know of another way to accomplish the same task, feel free to respond to the post or share it with a friend and get their opinion on it (just be nice about it). If you want to learn more about native mobile development, you can check out the other articles I have written here: https://medium.com/@jpmtech. If you want to see apps that have been built with native mobile development, you can check out my apps here: https://jpmtech.io/apps. Thank you for taking the time to check out my work!

--

--

Chase
Chase

Written by Chase

If you are interested in video content, subscribe to my YouTube channel: https://www.youtube.com/@jpmtechdev

No responses yet