¿Por qué tu aplicación Swift necesita una arquitectura basada en eventos?
Imagina que eres el director de una orquesta. Cada músico espera su parte para entrar en el momento adecuado. Si los violinistas tocaran todo a la vez, sería un caos. Más o menos así funciona la arquitectura basada en eventos en Swift: cada módulo reacciona solo a ciertos eventos, sin tirar de los hilos de otros módulos directamente.
Cuando me enfrenté por primera vez a la programación orientada a eventos en Swift en un proyecto comercial, me di cuenta de lo poderosa que es esta herramienta. Una aplicación de entrega de comida: el usuario presiona el botón «Pedir» — eso es un evento. El carrito se actualiza — evento. Llega un push con el repartidor — evento. Cada módulo (UI, red, BD local) simplemente se suscribe a los eventos necesarios y funciona de forma independiente. Eso es la arquitectura basada en eventos.
En este artículo, analizaremos tres enfoques para implementar la arquitectura de eventos en Swift: delegados clásicos, NotificationCenter y un bus de eventos personalizado. Verás código real, entenderás cuándo usar cada uno y podrás aplicarlo de inmediato en tu proyecto. ¡Vamos allá!
Fundamentos del enfoque basado en eventos en Swift
¿Qué es un evento en el contexto de Swift?
Un evento es una señal de que algo ha sucedido. Puede ser:
- Entrada del usuario (botón presionado, texto modificado)
- Cambio de datos (llegaron datos del servidor, se actualizó la BD)
- Notificaciones del sistema (la aplicación pasó a segundo plano, apareció el teclado)
El principio principal de la arquitectura basada en eventos en Swift es el acoplamiento débil (loose coupling). El emisor del evento no sabe quién lo manejará. El receptor no sabe quién lo envió. Se comunican a través de un bus de eventos — esto hace que el código sea flexible y comprobable.
Patrón Observer — el fundamento de los eventos
El patrón Observer en Swift es la base de cualquier sistema basado en eventos. Tenemos un objeto editor (Publisher) y múltiples suscriptores (Subscribers). Cuando el editor cambia de estado, notifica a todos los suscriptores.
En Swift hay varios mecanismos integrados para esto:
NotificationCenter— bus de eventos global en el SDK de iOS- Delegados — uno a uno, pero con control
Combine— framework reactivo de Apple (iOS 13+)- Implementaciones personalizadas — control total sobre el comportamiento
Analicemos cada enfoque con ejemplos.
Método 1. Delegados: un clásico del género
Los delegados en Swift son la forma más sencilla de implementar un evento. Es adecuado para relaciones «uno a uno», donde un objeto informa a otro sobre su estado.
Ejemplo: imagina que tenemos un cargador de imágenes que debe notificar al controlador cuando termine.
// 1. Definimos el protocolo delegadoprotocol ImageLoaderDelegate: AnyObject { func imageLoader(_ loader: ImageLoader, didLoad image: UIImage) func imageLoader(_ loader: ImageLoader, didFailWith error: Error)}
// 2. Clase editoraclass ImageLoader { weak var delegate: ImageLoaderDelegate?
func loadImage(from url: URL) { URLSession.shared.dataTask(with: url) { [weak self] data, _, error in DispatchQueue.main.async { if let error = error { self?.delegate?.imageLoader(self!, didFailWith: error) } else if let data = data, let image = UIImage(data: data) { self?.delegate?.imageLoader(self!, didLoad: image) } } }.resume() }}
// 3. Controlador suscriptorclass ViewController: UIViewController, ImageLoaderDelegate { let loader = ImageLoader() @IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() { super.viewDidLoad() lo