🖱️ En macOS, los usuarios esperan un comportamiento específico en las listas: un clic selecciona, doble clic ejecuta una acción principal y clic derecho muestra opciones.
📋 Para habilitar este patrón necesitas dos elementos clave: un inicializador de List que acepte el parámetro selection con binding, y el modificador contextMenu(forSelectionType:menu:primaryAction:). Primero define un tipo Identifiable y la propiedad de selección:
struct DocumentItem: Identifiable {
let id = UUID()
var title: String
var type: String
}
@State private var selectionID: DocumentItem.ID? = nil
🎯 El modificador contextMenu tiene tres partes esenciales: forSelectionType define el tipo de identificador, menu construye el menú contextual con botones de acción, y primaryAction define la acción del doble clic. Implementa la lista con el modificador completo:
List(documents, selection: $selectionID) { document in
HStack {
Image(systemName: iconName(for: document.type))
Text(document.title)
}
}
.contextMenu(forSelectionType: DocumentItem.ID.self) { selection in
if let id = selection.first,
let doc = documents.first(where: { $0.id == id }) {
Button("Abrir", systemImage: "square.and.arrow.up") {
open(doc)
}
Button("Renombrar", systemImage: "pencil") {
rename(doc)
}
}
} primaryAction: { selection in
guard let id = selection.first,
let doc = documents.first(where: { $0.id == id }) else { return }
open(doc)
}
💡 Un detalle importante: aunque parezca lógico usar onTapGesture(count: 2), este modificador no funciona correctamente en macOS. El enfoque correcto es primaryAction dentro de contextMenu.
⌨️ El teclado también funciona de forma nativa: las flechas arriba y abajo permiten navegar por la lista, y la tecla Return activa la acción primaria sin configuración adicional.
🎨 Para que toda la fila sea clicable usa .contentShape(.rect) en combinación con .frame. Esto asegura que el clic funcione en cualquier parte del elemento, no solo en el texto:
HStack {
Image(systemName: iconName(for: document.type))
Text(document.title)
}
.frame(height: 60)
.contentShape(.rect)
🔧 El parámetro selection en los closures (o bloques de código) de contextMenu es un Set que contiene los identificadores seleccionados. Para selección simple, accede con selection.first después de validar que no esté vacío.
👨💻 Dominar estas APIs marca la diferencia entre una app que funciona y una que se siente verdaderamente nativa en macOS. ¿Ya las usas en tus proyectos?


Deja un comentario