DEV Community

David Goyes
David Goyes

Posted on

Combine #1: ¡Hola, Combine! 

Combine: Asynchronous Programming with Swift

El framework Combine provee una aproximación declarativa sobre cómo procesar eventos en tu aplicación. En lugar de implementar múltiples llamados a delegados o closures, se puede crear una sola cadena de procesamiento para cierta fuente de eventos. Cada parte de la cadena es un operador de Combine que hace una acción diferente sobre los elementos recibidos del paso anterior.

Programación asíncrona

Podemos ejecutar código de forma secuencial o concurrente. En el caso de que se ejecute de forma concurrente en núcleos diferentes, es difícil determinar cuál va a ser el estado final del sistema. Lo que ocurre exactamente depende de condiciones estocásticas de la ejecución del programa, lo que implica que en cada ejecución se puede tener resultados diferentes.

Apple tiene varias estrategias para manejar concurrencia:

  1. NSThread
  2. Concurrencia moderna de Swift con async/await.
  3. NotificationCenter: Se ejecuta un bloque de código cuando se detecta la ocurrencia de un evento de interés.
  4. Patrón delegado: Un objeto actúa por, o en coordinación con otro objeto. En esta implementación, no se sabe cuándo se ejecutará este bloque o cuántas veces lo hará.
  5. Grand Central Dispatch y Operation: Se puede programar código para ejecutar de forma concurrente o serial en colas con ciertas prioridades.
  6. Closures: Se puede definir y pasar cierto bloque de código a un objeto, quien decidirá cuándo ejecutarlo.

Apple integró Combine a varios de sus frameworks (e.g. CoreData, SwiftUI, NotificationCenter, Timer, URLSession) de modo que sirva como interfaz de alto-nivel para diseñar y escribir código asíncrono.

Concurrencia moderna de Swift

Swift 5.5 introdujo un API para desarrollar código asíncrono y concurrente que permite suspender y reanudar el trabajo a discresión. Sin embargo, la ventaja de Combine radica en los operadores reactivos que facilitan el procesamiento de datos.

Inicios de Combine

Anteriormente se tenían las bibliotecas RxSwift y ReactiveSwift para programar de forma declarativa y reactiva en Swift, basadas en una biblioteca de Microsoft llamada Reactive Extensions para .NET (Rx.NET).
Combine implementa un estándar diferente pero similar a Rx llamado "Reactive Streams".

Bases de combine

Publishers

Un emisor (Publisher) puede emitir eventos de los siguientes tres tipos:

  1. Un valor de salida del tipo Publisher.Output. Si Publisher.Output es Int, el emisor no puede emitir ningún otro tipo de eventos (e.g. String o Date).
  2. Un evento de fin exitoso.
  3. Un evento de fin fallido, con un error de tipo Publisher.Failure. Si el emisor nunca falla entonces se debe declarar que este tipo es Never.

Operadores

Un operador (Operator) es un método que puede devolver el mismo o un nuevo emisor. Se los puede encadenar, llamando uno después de otro. No hay estado compartido, sino que hay una entrada ("upstream") que se convierte en una salida ("downstream").

Subscribers

Un suscriptor (Subscriber) "hace" algo con la salida emitida o con los eventos de fin.

Combine ofrece dos suscriptores por defecto:

  1. sink: Permite definir un closure para operar sobre la información recibida.
  2. assign: Permite conectar ("bind") la información recibida con alguna propiedad del modelo de datos o un control de la UI.

Es más fácil crear un suscriptor que un emisor.

Suscripciones

Un emisor (Publisher) solo emite eventos si tiene al menos un suscriptor (Suscriber). Se le llama "suscripción" a la cadena de emisor, con operadores y suscriptor.

En cuanto al manejo de memoria de las sucripciones: Toda suscripción retorna una referencia a un objeto de tipo Cancellable. Cuando ese objeto se libera de memoria, se cancela toda la suscripción y se liberan todos los recursos. También se puede tener una referencia a una colección de suscripciones con una variable de tipo [AnyCancellable].

Arquitectura de una aplicación

Combine es una herramienta agnóstica a la arquitectura elegida en la aplicación: Sirve para MVC, MVVM, VIPER, etc. No es necesario aplicarlo al 100% del sistema, sino que puede aplicarse de forma selectiva o incremental.


Cuestionario

  1. ¿Qué ventaja ofrece Combine frente al uso tradicional de delegados o closures para manejar eventos?
  2. ¿Cuál de las siguientes afirmaciones describe mejor a un Publisher en Combine?  a) Es un objeto que recibe y transforma datos.  b) Es un objeto que emite valores y eventos a lo largo del tiempo.  c) Es un objeto que siempre falla al emitir un valor.  d) Es una clase usada solo para manejar errores.
  3. Menciona dos frameworks de Apple que integran Combine de forma nativa.
  4. ¿Qué tipo de evento puede emitir un Publisher?  a) Solo valores numéricos.  b) Valores de salida, un fin exitoso o un error.  c) Solo un error en caso de fallo.  d) Solo eventos de fin de ejecución.
  5. ¿Cuál es la diferencia entre los suscriptores sink y assign en Combine?
  6. ¿Qué tipo de objeto se usa para cancelar una suscripción en Combine?  a) SubscriptionToken  b) CombineReference  c) Cancellable  d) AsyncTask
  7. Explica brevemente por qué la ejecución concurrente puede generar resultados diferentes en cada ejecución.
  8. ¿Cuál de las siguientes opciones no es una estrategia de Apple para manejar concurrencia?  a) NSThread  b) OperationQueue  c) ReactiveSwift  d) async/await
  9. ¿De qué biblioteca de Microsoft derivan los conceptos de programación reactiva en RxSwift y ReactiveSwift?
  10. ¿Por qué Combine se considera agnóstico respecto a la arquitectura de una aplicación (MVC, MVVM, VIPER, etc.)?

Solución

  1. ¿Qué ventaja ofrece Combine frente al uso tradicional de delegados o closures para manejar eventos? Es una capa de abstracción de alto nivel que permite unificar los distintos APIs de concurrencia de Apple.
  2. ¿Cuál de las siguientes afirmaciones describe mejor a un Publisher en Combine?  b) Es un objeto que emite valores y eventos a lo largo del tiempo. ✅
  3. Menciona dos frameworks de Apple que integran Combine de forma nativa. SwiftUI, Timer, NotificationCenter, CoreData
  4. ¿Qué tipo de evento puede emitir un Publisher?  b) Valores de salida, un fin exitoso o un error. ✅
  5. ¿Cuál es la diferencia entre los suscriptores sink y assign en Combine? sink crea un suscriptor con un closure con demanda ilimitada. assign reenvía los eventos a una propiedad del modelo de datos.
  6. ¿Qué tipo de objeto se usa para cancelar una suscripción en Combine?  c) Cancellable ✅
  7. Explica brevemente por qué la ejecución concurrente puede generar resultados diferentes en cada ejecución. El orden de ejecución depende de condiciones estocásticas del sistema.
  8. ¿Cuál de las siguientes opciones no es una estrategia de Apple para manejar concurrencia?  c) ReactiveSwift ✅
  9. ¿De qué biblioteca de Microsoft derivan los conceptos de programación reactiva en RxSwift y ReactiveSwift? Rx.NET de Microsoft.
  10. ¿Por qué Combine se considera agnóstico respecto a la arquitectura de una aplicación (MVC, MVVM, VIPER, etc.)? Se puede aplicar Combine bajo demanda a cualquier clase, y también de forma incremental de ser necesario.

Top comments (0)