Cualquier iOS Developer que lleve un tiempo en este mundo recuerda los días de UITableView en UIKit. Configurar el modo de edición requería lidiar con delegados, fuentes de datos, métodos como commit editingStyle y gestionar manualmente el estado de la interfaz. Era potente, sí, pero también propenso a errores y verboso.
Con la llegada de la programación Swift moderna y los paradigmas declarativos, Apple cambió las reglas del juego. Hoy en día, habilitar la edición de listas es tan simple como usar un EditButton en SwiftUI.
Sin embargo, detrás de esa aparente simplicidad hay un sistema basado en el entorno (Environment) que a veces puede confundir incluso a desarrolladores experimentados. En este extenso tutorial, exploraremos a fondo qué es, cómo funciona bajo el capó, y cómo implementar el EditButton en tus proyectos de Swift, abarcando las particularidades de Xcode al desarrollar para iOS, macOS y watchOS.
1. ¿Qué es el EditButton en SwiftUI?
El EditButton en SwiftUI es una vista preconfigurada proporcionada por el framework de Apple que alterna automáticamente el estado de edición de la vista actual.
En términos simples, es ese botón clásico que suele aparecer en la esquina superior derecha de una barra de navegación. Al tocarlo, cambia su texto de “Edit” a “Done” (o “Editar” a “OK” dependiendo del idioma del dispositivo), y pone a las vistas compatibles dentro de su jerarquía (usualmente un componente List) en modo de edición.
Este modo de edición revela controles de interfaz ocultos, como:
- Controles de eliminación: Los icónicos círculos rojos con un signo menos.
- Controles de reordenamiento: Las tres líneas horizontales (hamburguesa) a la derecha de la celda.
- Controles de selección múltiple: Círculos de verificación (checkboxes) para seleccionar varios elementos a la vez.
Pero el botón por sí solo no hace magia. Funciona en conjunto con los modificadores de la lista para transformar la experiencia del usuario.
2. Implementación Básica en iOS
Para un iOS Developer, la implementación más común de un EditButton en SwiftUI es dentro de una lista de elementos dinámicos. Vamos a construir una aplicación sencilla para gestionar un inventario.
Abre Xcode, crea un nuevo proyecto de SwiftUI y observa este código:
import SwiftUI
struct InventarioView: View {
@State private var items = ["MacBook Pro", "iPhone 15", "Apple Watch Ultra", "AirPods Pro"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
.onDelete(perform: eliminarItem)
.onMove(perform: moverItem)
}
.navigationTitle("Inventario")
.toolbar {
EditButton() // ¡Aquí está la magia!
}
}
}
// Función para eliminar elementos
func eliminarItem(at offsets: IndexSet) {
items.remove(atOffsets: offsets)
}
// Función para reordenar elementos
func moverItem(from source: IndexSet, to destination: Int) {
items.move(fromOffsets: source, toOffset: destination)
}
}
Analizando el Código:
ForEachdentro deList: Es vital entender que los modificadores.onDeletey.onMovese aplican alForEach, no a laListdirectamente. Esto se debe a que podrías tener secciones estáticas en tu lista que no quieres que sean editables.EditButton(): Lo colocamos dentro del modificador.toolbar. SwiftUI es lo suficientemente inteligente como para posicionarlo en el lugar estándar del sistema operativo (arriba a la derecha en iOS).- La Magia: Solo por incluir
EditButton(), SwiftUI conecta automáticamente el botón con la lista. Al pulsarlo, aparecerán los controles de borrado y reordenamiento.
3. Bajo el Capó: El Environment y el EditMode
Para dominar la programación Swift en interfaces declarativas, no basta con copiar y pegar. Debes entender por qué funciona.
El EditButton en SwiftUI no tiene una referencia directa a la List. No se pasan variables entre ellos. En su lugar, el botón modifica una variable de entorno (Environment Value) llamada editMode.
El editMode es un Binding<EditMode> opcional que fluye hacia abajo en la jerarquía de vistas. Los valores posibles de EditMode son:
.inactive: El estado normal..active: La lista está en modo de edición..transient: Un estado temporal (raramente usado directamente).
3.1. Leer el Estado de Edición
A veces, como iOS Developer, necesitas saber si la vista está en modo de edición para ocultar o mostrar otros elementos (por ejemplo, ocultar un botón de “Añadir Nuevo” mientras se está editando). Puedes leer este entorno así:
import SwiftUI
struct ListaConEstadoView: View {
@State private var items = ["Manzanas", "Peras", "Naranjas"]
// Leemos el valor del entorno
@Environment(\.editMode) private var editMode
var body: some View {
NavigationView {
VStack {
if editMode?.wrappedValue.isEditing == true {
Text("¡Estás en modo edición!")
.foregroundColor(.red)
.padding()
}
List {
ForEach(items, id: \.self) { item in
Text(item)
}
.onDelete { items.remove(atOffsets: $0) }
}
}
.navigationTitle("Frutas")
.toolbar {
EditButton()
}
}
}
}
3.2. Activar la Edición Sin el EditButton Pordefecto
Si el diseño de tu app requiere un botón personalizado (quizás un icono de un lápiz flotante en lugar del texto estándar en la barra de navegación), puedes inyectar y modificar el estado tú mismo.
Nota: Modificar el
editModemanualmente puede ser un poco verboso en SwiftUI debido a que requiere inyectar un@Statelocal en el.environment.
struct CustomEditView: View {
@State private var items = ["Swift", "Kotlin", "Python"]
@State private var isEditing: EditMode = .inactive // Nuestro estado local
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
.onDelete { items.remove(atOffsets: $0) }
}
.navigationTitle("Lenguajes")
// Sobrescribimos el entorno con nuestro estado local
.environment(\.editMode, $isEditing)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
withAnimation {
isEditing = isEditing == .active ? .inactive : .active
}
}) {
Image(systemName: isEditing == .active ? "checkmark.circle.fill" : "pencil.circle")
.font(.title2)
}
}
}
}
}
}
4. Selección Múltiple de Elementos
Otro caso de uso fantástico para el EditButton en SwiftUI es la selección múltiple. Imagina la aplicación de Correo (Mail), donde tocas “Editar” y aparecen círculos a la izquierda de cada correo para seleccionar varios y borrarlos de golpe.
Para lograr esto, simplemente pasas un enlace (Binding) a una propiedad de tipo Set en el inicializador de la List.
struct MultiSelectView: View {
@State private var items = ["Tarea 1", "Tarea 2", "Tarea 3", "Tarea 4"]
// Conjunto para almacenar los IDs de los elementos seleccionados
@State private var seleccion = Set<String>()
var body: some View {
NavigationView {
VStack {
// Pasamos el binding 'selection' a la lista
List(selection: $seleccion) {
ForEach(items, id: \.self) { item in
Text(item)
}
}
.navigationTitle("Tareas")
.toolbar {
EditButton()
}
if !seleccion.isEmpty {
Button(role: .destructive, action: borrarSeleccionados) {
Text("Borrar \(seleccion.count) tareas")
.frame(maxWidth: .infinity)
.padding()
.background(Color.red.opacity(0.1))
.cornerRadius(10)
}
.padding()
}
}
}
}
func borrarSeleccionados() {
items.removeAll { seleccion.contains($0) }
// Limpiamos la selección tras borrar
seleccion.removeAll()
}
}
Al tocar el EditButton, SwiftUI cambiará automáticamente la interfaz para mostrar las casillas de verificación en lugar de los botones de borrar individuales.
5. El EditButton en un Entorno Multiplataforma
SwiftUI promete “Aprende una vez, aplícalo en cualquier lugar”. Sin embargo, un buen iOS Developer sabe que las convenciones de interfaz de usuario varían enormemente entre iOS, macOS y watchOS. Veamos cómo se comporta el EditButton en cada entorno utilizando Xcode.
5.1. iOS y iPadOS
Este es el hábitat natural del EditButton. Funciona exactamente como hemos descrito a lo largo del tutorial. Se integra perfectamente en las barras de navegación, admite gestos de deslizamiento (swipe-to-delete) incluso sin estar en modo edición, y las animaciones son fluidas.
5.2. macOS
Aquí es donde la realidad golpea duro. En macOS, no existe el concepto tradicional del EditButton para listas.
Los usuarios de Mac no esperan hacer clic en un botón de “Editar” para borrar un elemento de una lista. Esperan:
- Hacer clic en un elemento para seleccionarlo y presionar la tecla
Retroceso(Backspace) oSuprimir. - Hacer clic derecho y seleccionar “Eliminar” en un menú contextual.
Si intentas compilar un EditButton() en un target de macOS en Xcode, simplemente no hará nada útil o ni siquiera se mostrará de forma estándar. En macOS, la eliminación se maneja mejor añadiendo un menú contextual y comandos de teclado:
// Ejemplo adaptado para macOS
List(selection: $seleccion) {
ForEach(items, id: \.self) { item in
Text(item)
.contextMenu {
Button("Eliminar") {
// Lógica de borrado
}
}
}
}
.onDeleteCommand {
// Se ejecuta al pulsar la tecla Suprimir en Mac
borrarSeleccionados()
}
5.3. watchOS
En el Apple Watch, el espacio es vital. El EditButton sí está disponible en watchOS, pero requiere un cuidado especial.
Generalmente, las listas en watchOS prefieren las acciones de deslizamiento (swipe actions). Sin embargo, si necesitas un modo de edición masiva o reordenamiento, puedes usarlo. En lugar de una barra de navegación superior (que apenas existe en watchOS), el botón suele colocarse en la barra de herramientas (.toolbar) y el sistema decidirá el mejor lugar para mostrarlo, a menudo requiriendo que el usuario desplace la vista hacia arriba.
6. Integración con Core Data y SwiftData
Cuando trabajas con persistencia de datos, borrar un elemento de un simple array de Strings no es suficiente. Debes asegurarte de eliminar el objeto real de la base de datos.
Si usas el nuevo y potente framework SwiftData junto con SwiftUI, el .onDelete funciona de forma gloriosa y limpia.
import SwiftUI
import SwiftData
struct BaseDeDatosView: View {
// Obtenemos el contexto de SwiftData
@Environment(\.modelContext) private var context
// Consultamos los datos
@Query private var notas: [Nota]
var body: some View {
NavigationStack {
List {
ForEach(notas) { nota in
Text(nota.titulo)
}
.onDelete(perform: borrarNota)
}
.navigationTitle("Mis Notas")
.toolbar {
EditButton()
}
}
}
func borrarNota(at offsets: IndexSet) {
for index in offsets {
let notaABorrar = notas[index]
context.delete(notaABorrar) // Borramos de la base de datos
}
// Nota: No necesitas guardar explícitamente, SwiftData tiene autosave
}
}
Aquí vemos el verdadero poder de la programación Swift: código conciso, legible y extremadamente eficiente.
Conclusión
El EditButton en SwiftUI es mucho más que un simple botón; es la puerta de entrada a todo un subsistema de manipulación de listas integrado en el entorno de SwiftUI. Atrás quedaron los días de implementar cinco métodos de delegado diferentes en Xcode solo para permitir que un usuario borre una fila.
Entender cómo el Environment maneja el editMode, saber cuándo utilizar métodos de selección múltiple, y, sobre todo, comprender las diferencias filosóficas de interfaz entre iOS, macOS y watchOS, te separará de un programador principiante y te consolidará como un iOS Developer versátil y profesional.
La programación Swift sigue evolucionando para hacer que las intenciones del desarrollador se traduzcan en código lo más rápido posible. Domina estas herramientas y tus aplicaciones no solo serán más robustas, sino mucho más agradables de construir.
Si tienes cualquier duda sobre este artículo, contacta conmigo y estaré encantado de ayudarte . Puedes contactar conmigo en mi perfil de X o en mi perfil de Instagram.










