SwiftUI – ActionSheet

Qué es ActionSheet

El componente ActionSheet permite crear una vista de selección de opciones nativa del sistema. Normalmente se usa para notificar al usuario sobre algo que ocurre en la aplicación o cuando debe tomar una decisión de aceptar o cancelar. Es un componente equivalente a UIAlertController de tipo .actionSheet de UIKit.  Puedes consultar la documentación oficial en este enlace.

Para crear el componente se usa el siguiente inicializador:

ActionSheet(title: Text("A question"), message: Text("Are you sure about that?"), buttons: [
                .default(Text("Yes"))
                .default(Text("No"))
                .default(Text("Maybe"))
                .destructive(Text("Delete"))
                .cancel()
            ])

El componente puede mostrar un título, una descripción y un listado de botones. Estos botones pueden ser del siguiente tipo:

  • .default. Es el estilo por defecto.
  • .cancel. Representa la cancelación de la acción.
  • .destructive. Representa la destrucción de algún dato.

Estos estilos llevan asociada una representación visual acorde a la que se puede encontrar en todo el sistema operativo, por lo que es recomendable usar cada uno de ellos dependiendo de la acción asociada a cada uno de ellos.

Para ejecutar alguna acción al pulsar los botones del ActionSheet se debe implementar el closure de cada uno de los botones que se ejecutará cuando se pulse cada botón.

ActionSheet(title: Text("A question"), message: Text("Are you sure about that?"), buttons: [
    .default(Text("Yes")) { /* Pressed button Yes. Do Something */ },
    .default(Text("No")) { /* Pressed button No. Do Something */ },
    .default(Text("Maybe")) { /* Pressed button Maybe. Do Something */ },
    .destructive(Text("Delete")) { /* Pressed button Delete. Do Something */ },
    .cancel()  { /* Pressed button Cancel. Do Something */ }
])

Cómo mostramos un ActionSheet

Un ActionSheet no se puede presentar de la misma forma que mostramos otros componentes de SwiftUI, ya que ni siquiera implementa el protocolo View.

Para mostrar un ActionSheet hay que usar el modificador actionSheet de View sobre la vista que queramos que lo presente. Este modificador necesita que la variable isPresented sea una variable de estado de tipo Bool, que será la encargada de indicar si el ActionSheet es visible (true) o no (false).

@State private var showActionSheet = false

...

.actionSheet(isPresented: $showActionSheet) {
        ActionSheet(title: Text("A question"), message: Text("Are you sure about that?"), buttons: [
            .default(Text("Yes")) { /* Pressed button Yes. Do Something */ },
            .default(Text("No")) { /* Pressed button No. Do Something */ },
            .default(Text("Maybe")) { /* Pressed button Maybe. Do Something */ },
            .destructive(Text("Delete")) { /* Pressed button Delete. Do Something */ },
            .cancel()  { /* Pressed button Cancel. Do Something */ }
        ])
}

En este ejemplo, la propiedad showActionSheet deberá ser seteada a true cuando queramos que se muestre el ActionSheet (por ejemplo cuando pulsemos un botón)

Está lógica es la misma que se usa con un NavigationLink cuando controlamos la navegación de forma manual.

Un ejemplo completo para mostrar un ActionSheet sería el siguiente:

struct ContentView: View {
    @State private var showActionSheet = false
    @State private var buttonPressed: String?
    
    var body: some View {
        VStack(spacing: 15) {
            Button("Show ActionSheet") {
                showActionSheet.toggle()
            }
            if let buttonPressed = buttonPressed {
                Text("You pressed "(buttonPressed)" button")
            }
            
        }
        .actionSheet(isPresented: $showActionSheet) {
            ActionSheet(title: Text("A question"), message: Text("Are you sure about that?"), buttons: [
                .default(Text("Yes")) { buttonPressed = "Yes" },
                .default(Text("No")) { buttonPressed = "No" },
                .default(Text("Maybe")) { buttonPressed = "Maybe" },
                .destructive(Text("Delete")) { buttonPressed = "Delete" },
                .cancel()  { buttonPressed = "Cancel" }
            ])
        }
    }
}

Modificadores comunes para ActionSheet

A diferencia de otros componentes, ActionSheet no tiene modificadores para poder personalizar su aspecto.

Ejemplo

Puedes encontrar este ejemplo en Github bajo el apartado ActionSheet.

Rafael Fernández,
iOS Tech Lider