Search code examples
swiftswiftuiactionalertswiftui-alert

Create an Alert with just one action button


I want an Alert with one button that runs some code. I do not want there to be a cancel button. I've only seen a way to have two buttons, with primaryButton and secondaryButton. Is there a way to do something like this?


Solution

  • When creating an Alert in SwiftUI the documentation is a great place to look to see what is available to you.

    In the Creating an Alert section we see the following:

    init(title: Text, message: Text?, primaryButton: Alert.Button, secondaryButton: Alert.Button)

    Creates an alert with two buttons.

    init(title: Text, message: Text?, dismissButton: Alert.Button?)

    Creates an alert with one button.

    As the documentation states, to create an Alert with one button you choose the second option.

    There are four different button types that you can use in an Alert, see here.

    static func cancel((() -> Void)?) -> Alert.Button

    An alert button that indicates cancellation.

    static func cancel(Text, action: (() -> Void)?) -> Alert.Button

    Creates an Alert.Button that indicates cancellation of some operation.

    static func default(Text, action: (() -> Void)?) -> Alert.Button

    Creates an Alert.Button with the default style.

    static func destructive(Text, action: (() -> Void)?) -> Alert.Button

    Creates an Alert.Button with a style indicating destruction of some data.

    So depending on what you want your button to do there are plenty of options to choose from. Notice that performing an action on a button is optional. So basically you can have your button do something or nothing if tapped.


    Alerts with no action

    These three alerts are identical in what they produce.

    Alert(title: Text("Alert Title"), message: Text("Alert message"), dismissButton: .default(Text("OK")))
    
    Alert(title: Text("Alert Title"), message: Text("Alert message"), dismissButton: .default(Text("OK"), action: nil))
    
    Alert(title: Text("Alert Title"), message: Text("Alert message"), dismissButton: .default(Text("OK"), action: {}))
    

    Because action is optional and its default value is nil we can either leave out, pass nil, or we can pass an empty closure. The first option is what I would go for if I wasn't performing an action.


    Alerts with an action

    If we wanted an action to be performed we just have to include it the action parameter. We can either write all our code in the closure that we pass or we can write it as a function.

    This alert has the code that should be run when action is tapped contained with the closure. This is ok if you have a single line of code to run, but it can start to clutter up your view if you have multiple lines of code.

    Alert(title: Text("Alert Title"),
          message: Text("Alert message"),
          dismissButton: .default(Text("OK"), action: { print("Hello")}))
    

    This Alert's action relies on a function that has been declared in the ContentView. This means that a function that it quite complicated won't clutter up your view code.

    struct ContentView: View {
    
        @State private var showAlert: Bool = false
    
        var body: some View {
            Button(action: { self.showAlert.toggle() },
                   label: { Text("Show Alert") })
            .alert(isPresented: $showAlert, content: {
                Alert(title: Text("Alert Title"),
                      message: Text("Alert message"),
                      dismissButton: .default(Text("OK"), action: self.hello))
            })
        }
    
        func hello() {
            print("Hello")
        }
    }