SwiftUI has two ways of creating alerts and sheets, and so far we’ve mostly only used one: a binding to a Boolean that shows the alert or sheet when the Boolean becomes true.
The second option allows us to bind an optional to the alert or sheet. The key is to use an optional Identifiable
object as the condition for showing the sheet, and the closure hands you the non-optional value that was used for the condition, so you can use it safely.
To demonstrate this, we could create a trivial User
struct that conforms to the Identifiable
protocol:
struct User: Identifiable {
var id = "Taylor Swift"
}
We could then create a property inside ContentView
that tracks which user is selected, set to nil
by default:
@State private var selectedUser: User? = nil
Now we can change the body
of ContentView
so that it sets selectedUser
to a value when a button is tapped, then displays a sheet when selectedUser
is given a value:
Button("Tap Me") {
selectedUser = User()
}
.sheet(item: $selectedUser) { user in
Text(user.id)
}
With that simple code, whenever you tap “Tap Me” a sheet saying “Taylor Swift” appears. As soon as the sheet is dismissed, SwiftUI sets selectedUser
back to nil
.
Alerts have similar functionality, although you need to pass both the Boolean and optional Identifiable
value at the same time. This allows you to show the alert when needed, but also benefit from the same optional unwrapping behavior we have with sheets.
First, add a Boolean property to watch:
@State private var isShowingUser = false
Then toggle that Boolean in your button's action:
isShowingUser = true
And finally change your sheet()
modifier for this:
.alert("Welcome", isPresented: $isShowingUser, presenting: selectedUser) { user in
Button(user.id) { }
}
With that covered, you now know practically all there is to know about sheets and alerts, but there is one last thing I want to sneak in to round out your knowledge.
When we're presenting a sheet, we can add presentation detents to make the sheet take up less than the full screen space. This is done using the presentationDetents()
modifier, which accepts a set of sizes to use for the sheet.
For example, we could specify medium and large sizes like this:
Text(selectedUser.id)
.presentationDetents([.medium, .large])
Because we're specifying two sizes here, the initial size will be used when the sheet is first shown, but iOS will show a little grab handle that lets users pull the sheet up to full size.
SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure and A/B test your entire paywall UI without any code changes or app updates.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.