¿Qué es @selector() en Swift y para qué sirve?
Si alguna vez has trabajado con Objective-C o te has encontrado con código heredado, seguramente has oído hablar de la mágica construcción @selector(). En Swift se transformó en #selector, pero la esencia sigue siendo la misma: es un puente entre el tipado estático de Swift y la naturaleza dinámica del runtime de Objective-C.
Imagina que necesitas pasar una referencia a un método como argumento. Por ejemplo, para manejar la pulsación de un botón o suscribirte a notificaciones. En Swift estamos acostumbrados a usar closures, pero las bibliotecas de Apple (UIKit, AppKit, Foundation) todavía dependen del viejo y confiable mecanismo de selectores. Aquí es donde @selector() en Swift se convierte en una herramienta indispensable.
En esta guía analizaremos:
- Cómo declarar correctamente selectores en Swift moderno
- Errores típicos y cómo evitarlos
- Ejemplos reales del desarrollo en iOS
- Cuándo usar
#selectory cuándo usar alternativas
De @selector() a #selector: evolución de la sintaxis
En Objective-C, un selector se ve así:
[@selector(buttonTapped:)]En Swift 2.0 apareció la construcción #selector, que se convirtió en el estándar. Así es como se ve ahora:
#selector(MyClass.buttonTapped(_:))La diferencia clave: #selector en Swift es verificado por el compilador. Si escribes mal el nombre del método o pasas una firma incorrecta, el compilador mostrará un error. Esto es una gran ventaja en comparación con Objective-C, donde un selector es solo una cadena y el error solo aparece en tiempo de ejecución.
Reglas para declarar métodos para #selector
El método que pasas a #selector debe ser:
- Accesible desde Objective-C — marcado con el atributo
@objc - No privado (o marcado como
@objc private) - Compatible en firma con lo que espera la parte llamante
Ejemplo de una declaración correcta:
class ViewController: UIViewController { @objc func buttonTapped(_ sender: UIButton) { print("¡Botón pulsado!") } override func viewDidLoad() { super.viewDidLoad() let button = UIButton(type: .system) button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside) }}Observa el @objc antes del método. Sin él, el compilador no permitirá usar #selector.
@selector() Swift: ejemplos prácticos
1. Target-Action: botones y gestos
El escenario más común para usar #selector es vincular acciones a elementos de la interfaz de usuario:
class ProfileViewController: UIViewController { @objc private func avatarTapped(_ gesture: UITapGestureRecognizer) { print("Avatar pulsado") } @objc private func settingsButtonPressed() { print("Abrir configuración") } override func viewDidLoad() { super.viewDidLoad() // Gesto let tapGesture = UITapGestureRecognizer(target: self, action: #selector(avatarTapped(_:))) avatarImageView.addGestureRecognizer(tapGesture) // Botón settingsButton.addTarget(self, action: #selector(settingsButtonPressed), for: .touchUpInside) }}Recuerda: si el método acepta un parámetro (por ejemplo, UITapGestureRecognizer), debes indicar _ en la firma del selector: #selector(avatarTapped(_:)).
2. PerformSelector y llamadas diferidas
A veces es necesario llamar a un método dinámicamente, especialmente al trabajar con KVO o temporizadores:
class TimerManager { @objc func fireTimer() {