Leave a rating/review
The Navigation View isn’t the only way to show new views in your app. SwiftUI also gives you a component type called Sheet.
You probably recognize this from the Apple Music App and the Mail app and it is a fantastic way to modally present a View on top of others in a swipable form.
All you need to do is provide a bindable boolean value to keep track of whether to display the sheet or not. If you set it true at any point, the sheet modifier will trigger display of the View for you.
You’re starting right from where you left off in the last episode.
Open up DetailView… And check out this little button with the location info in it.
You’re going to use this to bring a map of the artwork’s location up on screen.
So, like I said, the first step is to add a bindable boolean state property to keep track of presenting the map.
struct DetailView: View {
let artwork: Artwork
@State private var showMap = false
It’s set to false by default, because you don’t want it showing up first thing.
Now, you can make the map button do something by changing showMap to true.
HStack(alignment: .firstTextBaseline) {
Button(action: { showMap = true }) {
Image(systemName: "mappin.and.ellipse")
}
- The last step is to add a sheet.
- When showMap is set to true, the sheet will be presented.
- And the view you want to appear as a sheet goes in the closure. You’re going to use a custom LocationMap view that’s already set up for you. You’ll look at it in a minute.
.sheet(isPresented: $showMap) {
LocationMap(artwork: artwork)
}
Now you can try this out in the live preview!
Tap the map button.
There’s the location of the artwork.
and you can swipe down to dismiss it. That automatically changes whichever binding you’ve used to false for you!
Sometimes, though you want to cover the full screen so you can’t just swipe away. There’s another kind of modal view called fullscreencover. It actually has the same kind of initializer as the sheet.
.❌sheet❌🟢fullScreenCover(isPresented: $showMap)
But since you can’t just swipe to dismiss this, how do you go back?
Take a look at the view that you’re showing: LocationMap
It has this state property to store a region for the map, and a Map view, and just some text with the name of the location the map is showing.
You aren’t going to cover anything about working with maps in this course, but you will later on in this learning path!
In this HStack, you can add a button to dismiss this view…
HStack {
Text(self.artwork.locationName)
Spacer()
Button("Done") { }
You just need a way to change that Boolean from DetailView. And that way, is to add a binding to that bool in this LocationMap view!
@Binding var showModal: Bool
And then set it to false when this button is pressed.
Button("Done") { self.showModal = false }
You should get an error now, because the LocationMap in the preview needs a binding.
This is where constant bindings come in handy, so you can still see the map preview!
static var previews: some View {
LocationMap(artwork: artData[0], showModal: .constant(true))
}
Now update DetailView in the same way to pass along the real binding.
LocationMap(artwork: self.artwork, showModal: self.$showMap)
And give it a try in the live view!
That’s working as expected.
Now that you’ve got the hang of this, you can apply the same sort of technique to show other kinds of modal views with SwiftUI!
Things like alerts and popovers work very similarly. But I’ll leave you to check those out on your own.
Next up, a challenge to try out your SwiftUI Navigation Skills!