Programación reactiva en Swift: Combine y RxSwift para iOS/macOS

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Programación reactiva en Swift: Combine y RxSwift



La programación reactiva es un paradigma orientado a flujos de datos asíncronos y la propagación de cambios. En el ecosistema Swift (iOS/macOS), las herramientas principales para implementar este paradigma son el framework Combine (integrado en el SDK de Apple) y la biblioteca de terceros RxSwift. Ambas herramientas permiten describir declarativamente el manejo de eventos, reduciendo la cantidad de funciones callback y haciendo el código más legible y predecible.



En este artículo, exploraremos los conceptos clave de la programación reactiva, compararemos Combine y RxSwift, y proporcionaremos ejemplos prácticos para iOS y macOS.



Conceptos principales

En el enfoque reactivo subyacen tres entidades:



  • Publisher (Observable) — fuente de datos que genera eventos (valores, errores, finalización).
  • Subscriber (Observer) — consumidor que reacciona a los eventos.
  • Operator — función que transforma el flujo de datos (filtrado, transformación, combinación).


Ejemplo de un Publisher simple en Combine:

import Combine

let publisher = Just("¡Hola, Mundo Reactivo!")let subscription = publisher.sink { value in print(value)}// Salida: ¡Hola, Mundo Reactivo!


Combine vs RxSwift: comparación

Ambos frameworks resuelven tareas similares, pero tienen diferencias:



  • Combine — framework nativo de Apple (iOS 13+, macOS 10.15+). Utiliza tipado estricto y se integra con SwiftUI y URLSession.
  • RxSwift — biblioteca multiplataforma con una gran comunidad. Soporta versiones anteriores de iOS (desde iOS 8).
  • Rendimiento: Combine está optimizado para Apple Silicon, RxSwift puede ser más flexible en escenarios personalizados.


Ejemplos de código para iOS/macOS



1. Manejo reactivo de un campo de texto (Combine + UIKit)

Nos suscribimos a los cambios de texto en un UITextField:

import UIKitimport Combine

class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! private var cancellables = Set<AnyCancellable>() override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: textField) .compactMap { ($0.object as? UITextField)?.text } .debounce(for: .milliseconds(500), scheduler: RunLoop.main) .sink { text in print("El usuario ingresó: \\(text)") // Aquí se puede hacer una solicitud de red o actualizar la UI } .store(in: &cancellables) }}


2. Combinación de múltiples flujos (RxSwift para macOS)

Ejemplo de combinación de dos secuencias observables:

import RxSwift

let disposeBag = DisposeBag()

let firstObservable = Observable.of(1, 2, 3)let secondObservable = Observable.of("A", "B", "C")

Observable.zip(firstObservable, secondObservable) .subscribe(onNext: { (number, letter) in print("\\(number) -> \\(letter)") }) .disposed(by: disposeBag)

// Salida:// 1 -> A// 2 -> B// 3 -> C


3. Manejo de una solicitud de red usando Combine

Usamos URLSession para cargar datos:

import Combineimport Foundation

struct Post: Decodable { let id: Int let title: String}

func fetchPosts() -> AnyPublisher<[Post], Error> { let url = URL(string: "https://jsonplaceholder.typicode.com/posts")! return URLSession.shared.dataTaskPublisher(for: url) .map(\\.data) .decode(type: [Post].self, decoder: JSONDecoder()) .eraseToAnyPublisher()}

Recommendations