— SwiftUI, Binding, Programming — 1 min read
SwiftUI is a powerful framework for building user interfaces across all Apple platforms. One of its key features is the data flow mechanism, which includes property wrappers like @State
, @Binding
, @EnvironmentObject
, and more. In this article, we'll focus on @Binding
and how it can be used to control sheet navigation.
@Binding
is a property wrapper in SwiftUI that establishes a two-way connection between a property that stores data, and a view that displays and changes the data. It allows us to create a mutable state in one view and pass a reference to another view. This way, when the state changes in the second view, it also changes in the first view.
Let's consider the code below. This view is presented as a sheet and has a @Binding
variable showPurchaseModal
:
1import SwiftUI2
3struct OnboardingView: View {4 @Binding var showPurchaseModal: Bool5 6 var body: some View {7 VStack {8 Spacer()9 Text("Welcome to the App!")10 Spacer()11 Button {12 showPurchaseModal = true13 } label: {14 Text("Continue")15 }16 }17 .onDisappear {18 showPurchaseModal = true19 }20 }21}
In this example, when the "Continue" button is pressed or the OnboardingView
disappears, showPurchaseModal
is set to true
. This change is reflected in the parent view that owns the actual state.
Here's how the parent view might look:
1struct ContentView: View {2 @State private var showOnboarding = true3 @State private var showPurchaseModal = false4
5 var body: some View {6 VStack {7 Button {8 showOnboarding = true9 } label: {10 Text("Show Onboarding")11 }12 }13 .sheet(isPresented: $showOnboarding) {14 OnboardingView(showPurchaseModal: $showPurchaseModal)15 }16 .sheet(isPresented: $showPurchaseModal) {17 Text("Purchase Modal")18 }19 }20}
In ContentView
, showOnboarding
and showPurchaseModal
are @State
variables. When showPurchaseModal
changes in OnboardingView
, it also changes in ContentView
due to the @Binding
. This triggers a re-render of ContentView
, presenting the "Purchase Modal" sheet - after OnboardingView has disappeared(it doesn't matter if the user dismissed with a button or uses the gesture to hide the sheet).
If you aren't using the new NavigationStack
for routing in your app it's kind of difficult to replace one screen with another screen(if your app is still relying just on NavigationLink
for example). I personally wanted to show an onboarding screen and then show the user a different screen after that but also dismiss the onboarding screen. I already had the screen that I wanted to show wired up as a sheet
in the previous screen. I did do some experimenting with trying to use dismiss
but couldn't quite get the functionality I wanted and that's why I settled on the above solution and just past a @Binding that could be triggered in OnboardingView
instead.