NEW: Got a question? Get help on our new forums! >>

Using alert() and sheet() with optionals

Paul Hudson    @twostraws   

SwiftUI has two ways of creating alerts and sheets, and so far we’ve only been using one: a binding to a Boolean that shows the alert or sheet when the Boolean becomes true.

The second option isn’t used quite so often, but is really useful for the few times you need it: you can use an optional Identifiable object as your condition, and the alert or sheet will be shown when that object has a value. The closure for this variety 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 its text view is tapped, then uses alert(item:) to show an alert when selectedUser is given a value:

Text("Hello, World!")
    .onTapGesture {
        self.selectedUser = User()
    }
    .alert(item: $selectedUser) { user in
        Alert(title: Text(user.id))
    }

With that simple code, whenever you tap “Hello, World!” an alert saying “Taylor Swift” appears. As soon as the alert is dismissed, SwiftUI sets selectedUser back to nil.

This might seem like a simple piece of functionality, but it’s simpler and safer than the alternative. If we were to rewrite the above code using the old .alert(isPresented:) modifier it would look like this:

struct ContentView: View {
    @State private var selectedUser: User? = nil
    @State private var isShowingAlert = false

    var body: some View {
        Text("Hello, World!")
            .onTapGesture {
                self.selectedUser = User()
                self.isShowingAlert = true
            }
            .alert(isPresented: $isShowingAlert) {
                Alert(title: Text(selectedUser!.id))
            }
    }
}

That’s another property, another value to set in the onTapGesture(), and a force unwrap in the alert() modifier – if you can avoid those things you should.

Hacking with Swift is sponsored by Instabug

SPONSORED Catch bugs as soon as they happen and know exactly why a crash occurred by integrating Instabug's SDK in one minute. You will automatically receive device data, network logs, and reproduction steps with every bug and crash report.

Learn more and get started for free

Sponsor Hacking with Swift and reach the world's largest Swift community!

Cascable unleashes the power of your camera and unlocks powerful workflows for shooting, managing, and geotagging your photos.

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 5.0/5