<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: GoyesDev</title>
    <description>The latest articles on Forem by GoyesDev (@david_goyes_a488f58a17a53).</description>
    <link>https://forem.com/david_goyes_a488f58a17a53</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3646790%2F7fd821bf-6de1-467c-a6b6-0ffd90e943be.jpeg</url>
      <title>Forem: GoyesDev</title>
      <link>https://forem.com/david_goyes_a488f58a17a53</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/david_goyes_a488f58a17a53"/>
    <language>en</language>
    <item>
      <title>[SC] Swift Concurrency y CoreData</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Thu, 07 May 2026 00:07:53 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-swift-concurrency-y-coredata-2i8p</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-swift-concurrency-y-coredata-2i8p</guid>
      <description>&lt;h2&gt;
  
  
  Comprensión durante la lectura
&lt;/h2&gt;

&lt;p&gt;El autor sugiere seguir las mejores prácticas con CoreData. Para ello, pone un &lt;a href="https://github.com/AvdLee/CoreDataBestPractices" rel="noopener noreferrer"&gt;repositorio&lt;/a&gt; a disposición y una &lt;a href="https://www.avanderlee.com/category/core-data/" rel="noopener noreferrer"&gt;serie de artículos&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué Core Data requiere acceso seguro a hilos (&lt;code&gt;thread-safety&lt;/code&gt;)?
&lt;/h3&gt;

&lt;p&gt;No se puede pasar un &lt;code&gt;NSManagedObject&lt;/code&gt; de un hilo a otro.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué problema existe al pasar un &lt;code&gt;managed object&lt;/code&gt; de un hilo a otro?
&lt;/h3&gt;

&lt;p&gt;Un &lt;code&gt;NSManagedObject&lt;/code&gt; estéa ligado al &lt;code&gt;NSManagedObjectContext&lt;/code&gt; en el que fue creatdo y ese contexto solo es seguro usarlo desde el hilo en que fue creado. Si paso el objeto a otro hilo y acceso a sus propiedades puede ocurrir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Corrupción de datos silenciosa.&lt;/li&gt;
&lt;li&gt;Fallas impredecibles en tiempo de ejecución.&lt;/li&gt;
&lt;li&gt;Condiciones de carrera.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La solución tradicional es pasar solo el &lt;code&gt;NSManagedObjectID&lt;/code&gt; entre hilos y refetch del objeto en el contexto del hilo destino.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué el autor habla de Core Data en lugar de SwiftData?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SwiftData&lt;/code&gt; está teniendo más soporte de Apple. &lt;code&gt;CoreData&lt;/code&gt; parece un poco más "huérfano" y, además, es posible que haya muchos más proyectos usando esta biblioteca y gente teniendo problemas con ellos, que con &lt;code&gt;SwiftData&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué limitaciones tiene Core Data al integrarse con Swift Concurrency?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NSManagedObject&lt;/code&gt; no es &lt;code&gt;Sendable&lt;/code&gt;, lo que impide pasarlo entre actores o tareas concurrentes sin advertencias del compilador.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NSManagedObjectContext&lt;/code&gt; no es un &lt;code&gt;actor&lt;/code&gt;, así que no garantiza automáticamente acceso serializado.&lt;/li&gt;
&lt;li&gt;Métodos fundamentales como &lt;code&gt;loadPersistentStores&lt;/code&gt; no tienen equivalente &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; nativo.&lt;/li&gt;
&lt;li&gt;En modo estricto de concurrencia, muchas operaciones comunes de Core Data generan errores de compilación.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ¿Qué API asíncrona ofrece &lt;code&gt;NSManagedObjectContext&lt;/code&gt; para trabajar con &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext/perform(schedule:_:)" rel="noopener noreferrer"&gt;&lt;code&gt;perform(schedule:_:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué método de &lt;code&gt;NSPersistentContainer&lt;/code&gt; no tiene una alternativa asíncrona todavía?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/coredata/nspersistentcontainer/loadpersistentstores(completionhandler:)" rel="noopener noreferrer"&gt;&lt;code&gt;loadPersistentStores(completionHandler:)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es el &lt;em&gt;"persistent history tracking"&lt;/em&gt; y por qué se recomienda antes de migrar a Swift Concurrency?
&lt;/h3&gt;

&lt;p&gt;El &lt;em&gt;"persistent history tracking"&lt;/em&gt; es una funcionalidad de Core Data que registra todos los cambios realizados en el almacenamiento persistente en forma de transacciones (&lt;code&gt;NSPersistentHistoryTransaction&lt;/code&gt;). Esto permite que distintos contextos, extensiones de app o procesos se enteren de cambios ocurridos mientras no estaban activos.&lt;/p&gt;

&lt;p&gt;Se recomienda adaptarlo &lt;strong&gt;antes&lt;/strong&gt; de migrar a Swift Concurrency porque:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Establece una base sólida para sincronizar cambios entre múltiples contextos.&lt;/li&gt;
&lt;li&gt;Evita problemas de datos desactualizados cuando diferentes actores o tareas modifican el store simultáneamente.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Recordar sin releer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Puedes explicar con tus propias palabras por qué Core Data y Swift Concurrency no son totalmente compatibles aún?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué soluciones propone el autor para los casos en que Core Data no ofrece APIs asíncronas nativas?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la postura del autor respecto al futuro de SwiftData en el curso?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión y síntesis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuáles son las dos tecnologías principales que se integran en este módulo y cuál es el reto central entre ellas?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué recursos externos menciona el autor para profundizar o reportar problemas?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué conclusión puedes sacar sobre el estado actual de la adopción de Swift Concurrency en proyectos que usan Core Data?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>swiftconcurrency</category>
      <category>coredata</category>
    </item>
    <item>
      <title>[SC] Evitar ciclos de retención al usar Task</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Wed, 06 May 2026 23:39:21 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-evitar-ciclos-de-retencion-al-usar-task-5h0c</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-evitar-ciclos-de-retencion-al-usar-task-5h0c</guid>
      <description>&lt;h2&gt;
  
  
  Comprensión durante la lectura
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es exactamente un &lt;em&gt;"retain cycle"&lt;/em&gt; y por qué impide la desasignación de un objeto?
&lt;/h3&gt;

&lt;p&gt;Un ciclo de retención aparece cuando dos objetos tienen referencias fuertes entre ellos. ARC elimina los objetos cuando el contador de cada uno llega a cero, sin embargo, debido que los dos objetos se referencian entre sí, ARC no es capaz de eliminarlos y se produce una fuga de memoria.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿En qué situaciones concretas puede surgir un &lt;em&gt;"retain cycle"&lt;/em&gt; al usar &lt;code&gt;Task&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Aparece un ciclo de retención cuando un objeto retiene al &lt;code&gt;Task&lt;/code&gt; y este, a su vez, retiene al objeto directa o indirectamente (a través de una referencia hacia alguna de sus propiedades).&lt;/p&gt;

&lt;p&gt;Por otro lado, aunque no es un ciclo de retención estrictamente hablando, cuando el &lt;code&gt;Task&lt;/code&gt; tiene una referencia fuerte a un objeto y lo retiene hasta que termina de ejecutar, también puede resultar un comportamiento inesperado.&lt;/p&gt;

&lt;p&gt;El problema es especialmente delicado cuando el &lt;code&gt;Task&lt;/code&gt; se ejecuta por un tiempo prolongado, como cuando se usa &lt;code&gt;AsyncSequence&lt;/code&gt; para monitorear un evento a lo largo del tiempo. En este caso no se puede liberar al objeto retenido por el &lt;code&gt;Task&lt;/code&gt; mientras que esté monitoreando, para lo cual se requiere detener manualmente esta actividad para poder liberar la referencia.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la diferencia entre un &lt;em&gt;"retain cycle"&lt;/em&gt; y una &lt;em&gt;"one-way retention"&lt;/em&gt;?
&lt;/h3&gt;

&lt;p&gt;En un ciclo de retención, hay dos objetos que tienen referencias fuertes entre sí.&lt;/p&gt;

&lt;p&gt;En un "one-way retention", el objeto &lt;strong&gt;NO&lt;/strong&gt; retiene al &lt;code&gt;Task&lt;/code&gt;, pero el &lt;code&gt;Task&lt;/code&gt; &lt;strong&gt;SÍ&lt;/strong&gt; retiene al objeto y no deja que se libere hasta que haya terminado su trabajo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo y cuándo se puede romper un &lt;em&gt;"retain cycle"&lt;/em&gt; manualmente?
&lt;/h3&gt;

&lt;p&gt;El ciclo de retención puede romperse cuando se usa un &lt;code&gt;[weak self]&lt;/code&gt; para no crearlo inicialmente, y cuando se cancela explícitamente el &lt;code&gt;Task&lt;/code&gt; antes de liberar el objeto.&lt;/p&gt;

&lt;p&gt;Aquí es importante no depender del &lt;code&gt;deinit&lt;/code&gt; para la cancelación porque, precisamente, si hay un ciclo de retención, nunca se va a llamar el &lt;code&gt;deinit&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué limitaciones existen en Swift 6.2 respecto a &lt;code&gt;deinit&lt;/code&gt; y los actores?
&lt;/h3&gt;

&lt;p&gt;Antes de Swift 6.2, los &lt;code&gt;deinit&lt;/code&gt; eran &lt;code&gt;nonisolated&lt;/code&gt; y no podían llamar métodos aislados. Ahora, desde Swift 6.2, se pueden modificar el &lt;code&gt;deinit&lt;/code&gt; con &lt;code&gt;isolated&lt;/code&gt;. Esto permite a un &lt;code&gt;actor&lt;/code&gt; ejecutar métodos desde el &lt;code&gt;deinit&lt;/code&gt;. Sin embargo, no soluciona el problema del ciclo de retención - Como hay un ciclo de retención, nunca se va a llamar el &lt;code&gt;deinit&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recordar sin releer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cierra el artículo y explica con tus propias palabras qué es un retain cycle y cuándo ocurre con &lt;code&gt;Task&lt;/code&gt;.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Escribe de memoria las dos versiones del método de "polling" (&lt;code&gt;startPollingWithRetainCycle&lt;/code&gt; y sin él) y señala la diferencia clave.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Enumera las tres estrategias mencionadas para prevenir o romper &lt;em&gt;"retain cycles"&lt;/em&gt; (captura débil, cancelación explícita, &lt;code&gt;isolated deinit&lt;/code&gt;).
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión y síntesis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Revisa tus respuestas de la etapa Q y verifica si el artículo las respondió todas; anota dudas pendientes.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Escribe un mini-ejemplo propio (diferente al del artículo) donde un &lt;code&gt;Task&lt;/code&gt; podría causar un &lt;em&gt;"retain cycle"&lt;/em&gt; y cómo lo corregirias.
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] Manejo de Memoria en Swift Concurrency</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Wed, 06 May 2026 17:53:46 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-manejo-de-memoria-en-swift-concurrency-1nnh</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-manejo-de-memoria-en-swift-concurrency-1nnh</guid>
      <description>&lt;h2&gt;
  
  
  Comprensión durante la lectura
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es Swift Concurrency y por qué es relevante para el manejo de memoria?
&lt;/h3&gt;

&lt;p&gt;Swift Concurrency es un modelo de concurrencia de Swift que se basa en &lt;code&gt;Task&lt;/code&gt;s para ejecutar trabajo de forma asíncrona.&lt;/p&gt;

&lt;p&gt;Es relevante para el manejo de memoria porque las &lt;code&gt;Task&lt;/code&gt;s puede retener instancias y provocar comportamientos inesperados debido a su efecto retardado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿De qué manera capturan variables las &lt;code&gt;Task&lt;/code&gt; en Swift Concurrency, y en qué se parecen a los &lt;code&gt;closures&lt;/code&gt; normales?
&lt;/h3&gt;

&lt;p&gt;Un &lt;code&gt;Task&lt;/code&gt; puede retener una referencia de forma fuerte tanto de forma implícita como explícita (con el "capture list").&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué la concurrencia puede ocultar o agravar problemas de memoria en comparación con código síncrono?
&lt;/h3&gt;

&lt;p&gt;Una &lt;code&gt;Task&lt;/code&gt; podría estar reteniendo un objeto que, en cierto momento se asume que ya fue liberado. Sin embargo, debido a su naturaleza asíncrona, el efecto de haber retenido dicho objeto puede aparecer más tarde, y esto puede ser difícil de rastrear.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué sucede con un objeto cuando una &lt;code&gt;Task&lt;/code&gt; captura &lt;code&gt;self&lt;/code&gt; de forma fuerte (strong reference) y el objeto se establece en &lt;code&gt;nil&lt;/code&gt; antes de que la tarea termine?
&lt;/h3&gt;

&lt;p&gt;El objeto se libera después de que la &lt;code&gt;Task&lt;/code&gt; termina.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la diferencia en el comportamiento del ciclo de vida del objeto cuando se usa &lt;code&gt;[weak self]&lt;/code&gt; dentro de una &lt;code&gt;Task&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Al usar &lt;code&gt;[weak self]&lt;/code&gt;, ARC puede liberar &lt;code&gt;self&lt;/code&gt; durante la suspensión del &lt;code&gt;Task&lt;/code&gt;. Cuando la tarea reanuda después de &lt;code&gt;await&lt;/code&gt;, &lt;code&gt;self&lt;/code&gt; puede ser &lt;code&gt;nil&lt;/code&gt; por lo que las llamadas posteriores a &lt;code&gt;self&lt;/code&gt; no se ejecutan.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué significa que los actores (&lt;code&gt;actors&lt;/code&gt;) gestionan su memoria de forma independiente y serializan el acceso a sus propiedades?
&lt;/h3&gt;

&lt;p&gt;Los actores sincronizan el acceso a su memoria a través de un executor. De este modo, todo cliente que quiera modificar una propiedad tendrá que hacerlo a través de un método accesor &lt;code&gt;async&lt;/code&gt;, y se puede leer directamente accediendo con &lt;code&gt;await&lt;/code&gt; a la propiedad.&lt;/p&gt;

&lt;h3&gt;
  
  
  Según el artículo, ¿en qué orden aparecen los mensajes impresos cuando &lt;code&gt;fetchData()&lt;/code&gt; captura &lt;code&gt;self&lt;/code&gt; fuertemente y el &lt;code&gt;viewModel&lt;/code&gt; se pone en &lt;code&gt;nil&lt;/code&gt;? ¿Por qué ocurre ese orden?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;@MainActor&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ContentViewModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;deinit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Deinit!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;performNetworkRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;updateUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// ⚠️ Captures self strongly!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;updateUI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Update UI!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;performNetworkRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Perform network request"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Finished network request"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ContentViewModel&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;viewModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Set viewModel to nil"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imprime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Perform network request&lt;/span&gt;
&lt;span class="c1"&gt;// Set viewModel to nil&lt;/span&gt;
&lt;span class="c1"&gt;// Finished network request&lt;/span&gt;
&lt;span class="c1"&gt;// Update UI!&lt;/span&gt;
&lt;span class="c1"&gt;// Deinit!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El &lt;code&gt;deinit&lt;/code&gt; se llama al final, incluso aunque se puso &lt;code&gt;viewModel = nil&lt;/code&gt; porque la &lt;code&gt;Task&lt;/code&gt; retuvo el objeto.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué ocurre con &lt;code&gt;performNetworkRequest()&lt;/code&gt; cuando se usa &lt;code&gt;[weak self]&lt;/code&gt; y el objeto se libera a mitad de la ejecución?
&lt;/h3&gt;

&lt;p&gt;La petición simulada termina después de que se libera el objeto en cuestión. Luego, cuando el flujo de control regresa al &lt;code&gt;Task&lt;/code&gt;, las instrucciones siguientes no se ejecutan porque &lt;code&gt;self&lt;/code&gt; es &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recordar sin releer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sin mirar el artículo, ¿puedes explicar con tus propias palabras por qué una &lt;code&gt;Task&lt;/code&gt; puede mantener vivo un objeto más tiempo del esperado?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuáles son las dos formas de capturar &lt;code&gt;self&lt;/code&gt; dentro de una &lt;code&gt;Task&lt;/code&gt; que muestra el artículo, y cuál es la consecuencia de cada una?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión y síntesis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la conclusión principal del artículo sobre el manejo de memoria en Swift Concurrency respecto al código normal?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué impacto práctico puede tener una retención prolongada de objetos en el rendimiento de una aplicación?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué temas o ejemplos adicionales anticipa el artículo que se cubrirán en la siguiente lección?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
      <category>ios</category>
    </item>
    <item>
      <title>[SC] Control del dominio de aislamiento por defecto en Swift 6.2</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Wed, 06 May 2026 17:44:43 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-control-del-dominio-de-aislamiento-por-defecto-en-swift-62-27ea</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-control-del-dominio-de-aislamiento-por-defecto-en-swift-62-27ea</guid>
      <description>&lt;h2&gt;
  
  
  Comprensión durante la lectura
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué significa exactamente &lt;em&gt;"dominio de aislamiento por defecto"&lt;/em&gt; y por qué importa en Swift Concurrency?
&lt;/h3&gt;

&lt;p&gt;Los tipos de datos (funciones y propiedades globales) en Swift 6.2 viven en algún tipo de aislamiento, bien sea &lt;code&gt;nonisolated&lt;/code&gt; o un &lt;code&gt;actor&lt;/code&gt; específico.&lt;/p&gt;

&lt;p&gt;Como la mayoría de aplicaciones comienzan en el hilo principal y solo cambian de hilo si se introduce concurrencia explícitamente (lo que implica que la mayoría de tipos de datos vivirían en el mismo dominio de aislamiento &lt;code&gt;MainActor&lt;/code&gt;), hay una funcionalidad opcional en Xcode 26 que permite marcar todos los tipos de datos dentro de un dominio de aislamiento por defecto. Este dominio de aislamiento puede ser &lt;code&gt;MainActor&lt;/code&gt; (anteriormente era &lt;code&gt;nonisolated&lt;/code&gt; por defecto).&lt;/p&gt;

&lt;p&gt;Esta funcionalidad es importante porque, antes de que existiera, aparecía un montón de advertencias en todos los tipos de datos debido a que se asumía que todas eran &lt;code&gt;nonisolated&lt;/code&gt;, pese a que de alguna manera estaban relacionadas con tipos de datos de &lt;code&gt;MainActor&lt;/code&gt;. Silenciar una advertencia por un lado, podía levantar otra por otro lado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué tantos desarrolladores terminaban añadiendo &lt;code&gt;@MainActor&lt;/code&gt; en todas partes?
&lt;/h3&gt;

&lt;p&gt;La aplicación de iOS podía iniciar en &lt;code&gt;@MainActor&lt;/code&gt; y no cambiar de hilo, sino hasta ejecutar alguna tarea específica.&lt;/p&gt;

&lt;p&gt;El compilador no podía asumir que todas las clases no marcadas con &lt;code&gt;@MainActor&lt;/code&gt; vivían dentro del dominio de &lt;code&gt;MainActor&lt;/code&gt;, incluso aunque el desarrollador supiera que así ocurría, y que no había ningún riesgo de introducir una carrera de datos. Por esta razón, el desarrollador tenía que marcar todas las clases con &lt;code&gt;@MainActor&lt;/code&gt;. Ahora, todas traen &lt;code&gt;@MainActor&lt;/code&gt; implícito y, en caso de no querer este dominio de aislamiento, se tiene que cambiar manualmente.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia hay entre &lt;code&gt;nonisolated&lt;/code&gt; y &lt;code&gt;@MainActor&lt;/code&gt; como dominio por defecto?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;nonisolated&lt;/code&gt; por defecto, indica que el código no está aislado en ningún dominio de aislamiento específico, por lo que el compilador no puede asegurar la ausencia de carreras de datos. &lt;strong&gt;ATENCIÓN:&lt;/strong&gt; Esto no significa que &lt;strong&gt;HABRÁ&lt;/strong&gt; una carrera de datos - Puede no haberla. Solo quiere decir que no se puede asegurar que no la haya.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@MainActor&lt;/code&gt; por defecto, indica que todo el código está aislado en &lt;code&gt;MainActor&lt;/code&gt;, a no ser que se indique lo contrario. Esto asegura que no haya carreras de datos entre los llamados.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se configura el dominio de aislamiento por defecto en un proyecto Xcode y en un paquete Swift?
&lt;/h3&gt;

&lt;p&gt;En un proyecto de Xcode hay que cambiar "default actor isolation".&lt;/p&gt;

&lt;p&gt;En el caso del paquete de Swift, se puede aplicar el setting &lt;a href="https://developer.apple.com/documentation/packagedescription/swiftsetting/defaultisolation(_:_:)" rel="noopener noreferrer"&gt;&lt;code&gt;SwiftSetting.defaultIsolation(_:_:)&lt;/code&gt;&lt;/a&gt;, teniendo en cuenta que puede recibir como aislamiento &lt;code&gt;MainActor.self&lt;/code&gt; o &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tomar como referencia el siguiente código para configurar un paquete de Swift:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;PackageDescription&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MyPackage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MyTarget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;swiftSettings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ENABLE_FEATURE_A"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DEBUG_MODE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableUpcomingFeature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ExistentialAny"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;testTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MyTargetTests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"MyTarget"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ¿Por qué tiene sentido que la mayoría del código de una app corra en el hilo principal por defecto?
&lt;/h3&gt;

&lt;p&gt;La mayoría de código de una app inicia en el hilo principal y permanece allí hasta que explícitamente se introduce concurrencia. En este escenario, si todo corre secuencial, no hay carreras de datos, así que asumir que el código está en &lt;code&gt;nonisolated&lt;/code&gt; provoca falsas alarmas. En lugar de eso, es mejor asumir por defecto que el código corre en el hilo principal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Según el ejemplo de código del artículo, ¿qué ocurre con la inferencia de aislamiento en &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;struct&lt;/code&gt;s y &lt;code&gt;actor&lt;/code&gt; cuando se usa &lt;code&gt;@MainActor&lt;/code&gt; como valor por defecto?
&lt;/h3&gt;

&lt;p&gt;Al usar &lt;code&gt;@MainActor&lt;/code&gt; como valor por defecto, &lt;code&gt;class&lt;/code&gt; y &lt;code&gt;struct (junto con atributos y métodos), vivirán en&lt;/code&gt;MainActor&lt;code&gt;. Al crear un&lt;/code&gt;actor&lt;code&gt;, sus métodos&lt;/code&gt;init&lt;code&gt;y&lt;/code&gt;deinit&lt;code&gt;serán&lt;/code&gt;nonisolated` y el resto estarán aislados dentro del dominio de aislamiento definido por él mismo.&lt;/p&gt;

&lt;p&gt;En el caso de que &lt;code&gt;class&lt;/code&gt; y &lt;code&gt;struct&lt;/code&gt; conformen un protocolo, estos heredarán el dominio de aislamiento definido para el protocolo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recordar sin releer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Este cambio rompe proyectos existentes? ¿Por qué sí o por qué no?
&lt;/h3&gt;

&lt;p&gt;No rompe proyectos existentes el cambio es opcional. Si no se aplica, entonces el código asume por defecto &lt;code&gt;nonisolated&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿El ajuste se aplica globalmente a todo el proyecto o hay que configurarlo módulo por módulo?
&lt;/h3&gt;

&lt;p&gt;Hay que configurarlo por módulo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Revisión y síntesis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuál es el impacto práctico de cambiar el dominio de aislamiento en la migración a Swift 6?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué riesgos menciona el equipo de Swift respecto a tener dialectos de lenguaje distintos según el módulo?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] nonisolated(nonsending) y @concurrent</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Tue, 28 Apr 2026 22:10:03 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-nonisolatednonsending-y-concurrent-91k</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-nonisolatednonsending-y-concurrent-91k</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la diferencia entre el comportamiento anterior y el nuevo de las funciones &lt;code&gt;nonisolated async&lt;/code&gt; a partir de Swift 6.2?
&lt;/h3&gt;

&lt;p&gt;Antes de Swift 6.2, las funciones &lt;code&gt;nonisolated async&lt;/code&gt; se ejecutaban de forma independiente, &lt;strong&gt;sin heredar el contexto de ejecución&lt;/strong&gt;. Esto significa que cada función &lt;code&gt;nonisolated async&lt;/code&gt; es una sub-tarea que decide por sí misma dónde ejecutarse. Si se anota con &lt;code&gt;@MainActor&lt;/code&gt; o algún &lt;code&gt;@globalActor&lt;/code&gt;, entonces se va a ejecutar en el &lt;code&gt;executor&lt;/code&gt; de dicho actor. En caso contrario, se va a ir a un hilo de segundo plano.&lt;/p&gt;

&lt;p&gt;A partir de Swift 6.2 las funciones &lt;code&gt;nonisolated async&lt;/code&gt; corren, por defecto, en al actor invocador.&lt;/p&gt;

&lt;p&gt;Para rechazar la herencia de dominio de aislamiento, se debe marcar el método específicamente con el atributo &lt;code&gt;@concurrent&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Bajo qué circunstancias una tarea (&lt;code&gt;Task&lt;/code&gt;) puede ejecutarse en el hilo principal en lugar de en un hilo en segundo plano?
&lt;/h3&gt;

&lt;p&gt;Una &lt;code&gt;Task&lt;/code&gt; se puede ejecutar en el hilo principal si está marcada con &lt;code&gt;@MainActor&lt;/code&gt;, o si fue invocada por una tarea marcada con &lt;code&gt;@MainActor&lt;/code&gt; en Swift 6.2.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Para qué sirve el atributo &lt;code&gt;@concurrent&lt;/code&gt; y cuándo se debe usar?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@concurrent&lt;/code&gt; sirve para que un método &lt;code&gt;nonisolated async&lt;/code&gt; &lt;strong&gt;NO&lt;/strong&gt; herede el contexto del método invocador.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué problema resuelve &lt;code&gt;nonisolated(nonsending)&lt;/code&gt; y cuándo es apropiado aplicarlo?
&lt;/h3&gt;

&lt;p&gt;En caso de que la propiedad &lt;code&gt;NonisolatedNonsendingByDefault&lt;/code&gt; esté puesta en &lt;code&gt;NO&lt;/code&gt;, puede aparecer un error como &lt;code&gt;Sending value of non-Sendable type ‘MyType’ risks causing data races&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Este error aparece porque Swift asume que, sin &lt;code&gt;nonisolated(nonsending), la función va a correr en un dominio de aislamiento diferente al del llamador. Cuando eso pasa, Swift necesita enviar el valor (&lt;/code&gt;self&lt;code&gt;u otros parámetros) de un dominio a otro - y si el tipo no es&lt;/code&gt;Sendable`, el compilador dice: "Peligro, datarace!".&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nonisolated(nonsending)&lt;/code&gt; le dice al compilador: "Esta función va a heredar el dominio de aislamiento del llamador, así que no hay ningún envío entre dominios".&lt;/p&gt;

&lt;p&gt;Si no hay envío, no hay riesgo de data race.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nonisolated(nonsending)&lt;/code&gt; no es una solución mágica universal. Funciona solo cuando de verdad estoy de acuerdo con que la función bloquee el actor del llamador.&lt;/p&gt;

&lt;p&gt;Si la función hace algo pesado, usar &lt;code&gt;nonisolated(nonsending)&lt;/code&gt; podría bloquear el hilo en cuestión. En ese caso, la solución correcta sería hacer el tipo &lt;code&gt;Sendable&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se puede verificar en qué hilo se está ejecutando una tarea durante el desarrollo?
&lt;/h3&gt;

&lt;p&gt;Usar &lt;code&gt;Thread.current&lt;/code&gt;. Teniendo en cuenta que posiblemente sea necesario usar la extensión:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;swift&lt;br&gt;
extension Thread {&lt;br&gt;
  public static var currentThread: Thread {&lt;br&gt;
    return Thread.current&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Por otro lado, siempre se puede poner un punto de quiebre para mirar en qué hilo se está parado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿cómo explica el autor que el actor de llamada puede influir en el hilo donde se ejecuta una tarea?
&lt;/h3&gt;

&lt;p&gt;El actor del llamador determina dónde empieza la tarea y a dónde regresa después de cada punto de suspensión.&lt;/p&gt;

&lt;p&gt;En el ejemplo del artículo:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`swift&lt;br&gt;
@MainActor&lt;br&gt;
private func updateUI() {&lt;br&gt;
  Task {&lt;br&gt;
    print("Starting on the main thread")&lt;br&gt;
    await someBackgroundTask()&lt;br&gt;
    print("Resuming on the main thread")&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;private func someBackgroundTask() async {&lt;br&gt;
    print("Background task on thread: 8")&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;someBackgroundTask()&lt;/code&gt; corre en el hilo 8. No obstante, la primera línea del &lt;code&gt;Task&lt;/code&gt; de &lt;code&gt;updateUI() corre en el hilo 1, y después de la suspensión de &lt;/code&gt;await someBackgroundTask()`, el trabajo regresa al hilo 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué cambio introduce SE-461 y cuál es la justificación filosófica que da el autor al citarlo?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/swiftlang/swift-evolution/blob/main/proposals/0461-async-function-isolation.md" rel="noopener noreferrer"&gt;SE-461: Run nonisolated async functions on the caller’s actor by default&lt;/a&gt; hace que las funciones &lt;code&gt;nonisolated async&lt;/code&gt; hereden el contexto del método invocador. En caso de no querer que esto pase, entonces hay que marcar con el atributo &lt;code&gt;@concurrent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El comportamiento anterior de las funciones &lt;code&gt;nonisolated async&lt;/code&gt; sacrificaba usabilidad innecesariamente para proteger la responsividad del hilo principal.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recitación
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿puedes explicar con tus palabras qué ocurre cuando una función nonisolated es llamada desde un contexto &lt;code&gt;@MainActor&lt;/code&gt; en Swift 6.2 con el nuevo flag activado?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuándo elegirías &lt;code&gt;@concurrent&lt;/code&gt; y cuándo &lt;code&gt;nonisolated(nonsending)&lt;/code&gt;? ¿Puedes describir un caso de uso para cada uno?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cómo habilitarías el nuevo comportamiento de &lt;code&gt;NonisolatedNonsendingByDefault&lt;/code&gt; en un proyecto de Xcode?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cómo se relacionan los conceptos de actor isolation, &lt;code&gt;@MainActor&lt;/code&gt; y el pool cooperativo de hilos de Swift?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Por qué el autor advierte que este cambio puede confundir a quienes ya conocían Swift Concurrency antes de la versión 6.2?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué implicaciones de rendimiento puede tener el nuevo comportamiento por defecto si no se usa &lt;code&gt;@concurrent&lt;/code&gt; donde corresponde?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿En qué se diferencia el error de compilación "Sending value of non-Sendable type" del problema que resuelve &lt;code&gt;nonisolated(nonsending)&lt;/code&gt;?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] Puntos de suspensión de una Task</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Tue, 28 Apr 2026 16:33:05 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-puntos-de-suspension-de-una-task-4hjk</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-puntos-de-suspension-de-una-task-4hjk</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es exactamente un punto de suspensión en una tarea de Swift?
&lt;/h3&gt;

&lt;p&gt;Un punto de suspensión es un momento donde una &lt;code&gt;Task&lt;/code&gt; puede pausar su ejecución para permitir que otro trabajo pueda ejecutarse.&lt;/p&gt;

&lt;p&gt;Cada uso de &lt;code&gt;await&lt;/code&gt; es un punto de suspensión potencial.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué no todo &lt;code&gt;await&lt;/code&gt; garantiza una suspensión real?
&lt;/h3&gt;

&lt;p&gt;Si la tarea esperada (&lt;code&gt;await&lt;/code&gt;) puede ser completada de forma síncrona, la tarea de origen no se suspende sino que seguirá ejecutando inmediatamente. Esto puede ocurrir cuando el método asíncrono pertenece al mismo dominio de aislamiento. &lt;code&gt;await&lt;/code&gt; simplemente marca un posible punto de suspensión, no uno garantizado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es la reentrada de actores y cuándo ocurre?
&lt;/h3&gt;

&lt;p&gt;Un &lt;code&gt;actor&lt;/code&gt; garantiza que solo una &lt;code&gt;Task&lt;/code&gt; puede acceder a su estado aislado a la vez. Sin embargo, si una tarea encuentra un punto de suspensión dentro del actor, existe la posibilidad de que otra tarea empiece a trabajar con el actor antes de que la primera termine.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué riesgos concretos introduce un punto de suspensión dentro de un actor?
&lt;/h3&gt;

&lt;p&gt;Todo estado mutable que asume una ejecución ininterrumpida podría comportarse de forma incorrecta si la tarea es suspendida. Esto puede derivar en un estado inconsistente porque podría solaparse con otra tarea que podría mutar el estado del actor antes de que la primera termine.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se puede evitar el comportamiento inesperado por reentrada?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Evitar modificar el estado mutable de un actor después de un punto de suspensión.&lt;/li&gt;
&lt;li&gt;Guardar información importante para el desarrollo del método en variables locales.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ¿Qué cambia exactamente en la versión corregida del método &lt;code&gt;deposit&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;El punto de suspensión aparece después de modificar el estado del actor. Todas las modificaciones al estado del actor se agrupan antes del &lt;code&gt;await&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Antes&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;] Deposited &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;, balance is now &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;logTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ⚠️ Suspension point&lt;/span&gt;

  &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// bonus after logging&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;] Applied bonus, balance is now &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Después&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;] Deposited &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;, balance is now &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// bonus after logging&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;] Applied bonus, balance is now &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;logTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// ⚠️ Suspension point&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Recitación / comprensión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Explica con tus propias palabras por qué el balance pasa de 100 → 200 en lugar de 100 → 110.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la diferencia entre un punto de suspensión posible y uno garantizado?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Por qué mover el &lt;code&gt;await&lt;/code&gt; al final del método soluciona el problema de reentrada?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión y síntesis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la regla práctica más importante para mutar el estado de un actor de forma segura?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿En qué situaciones de tu propio código deberías revisar dónde caen los puntos de suspensión?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué tema cubre la siguiente lección y cómo se relaciona con lo aprendido aquí?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] Deshacerse de la mentalidad de hilos</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Tue, 28 Apr 2026 15:36:04 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-deshacerse-de-la-mentalidad-de-hilos-2bod</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-deshacerse-de-la-mentalidad-de-hilos-2bod</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Por qué Swift Concurrency quiere que dejes de controlar manualmente los hilos?
&lt;/h3&gt;

&lt;p&gt;Controlar manualmente los hilos trae los siguientes costos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Costo elevado en memoria (stack de cada thread)&lt;/li&gt;
&lt;li&gt;Intercambio de contextos innecesariamente alto (más trabajo para los procesadores)&lt;/li&gt;
&lt;li&gt;problemas de inversión de prioridad.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Debido a los problemas anteriores, Swift Concurrency nos invita a dejar que el framework se encargue del manejo de hilos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es un dominio de aislamiento y cómo reemplaza el concepto de hilo?
&lt;/h3&gt;

&lt;p&gt;Un dominio de aislamiento es una región o contexto al que pertenece un fragmento de código. Este contexto determina cómo ejecutar el código de forma segura y sin carreras de datos.&lt;/p&gt;

&lt;p&gt;El cambio de paradigma consiste en que ahora se declara a qué dominio pertenece el código y Swift se encarga de ejecutarlo de forma segura, en el hilo que considere más eficiente.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué papel juegan los actores (&lt;code&gt;actors&lt;/code&gt;) en Swift Concurrency?
&lt;/h3&gt;

&lt;p&gt;Todo el código definido dentro un &lt;code&gt;actor&lt;/code&gt; pertenece a su dominio de aislamiento y es ejecutado por un &lt;code&gt;executor&lt;/code&gt; independiente, lo que garantiza que el código se ejecute de forma serial dentro del actor, evitando acceso concurrentes a su estado interno.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se le dan "pistas" al sistema sobre la prioridad de una tarea?
&lt;/h3&gt;

&lt;p&gt;La "prioridad" de una tarea no establece directamente el orden de ejecución del código, sino que sugiere al runtime el nivel de importancia que tiene el bloque a ejecutar.&lt;/p&gt;

&lt;p&gt;Sin embargo, puede darse el caso que tenga una tarea de prioridad alta que esté esperando a que una tarea de prioridad baja termine. Por esto se dice que la "prioridad" de una tarea es más bien una sugerencia.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué una tarea de alta prioridad no garantiza ejecución inmediata?
&lt;/h3&gt;

&lt;p&gt;La prioridad de una "tarea" es una sugerencia para el runtime. No se está asignando la tarea a un hilo, sino que se está indicando la naturaleza del trabajo a realizar.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué problema resuelve la conformancia con &lt;code&gt;Sendable&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Un dato &lt;code&gt;Sendable&lt;/code&gt; es seguro para cruzar dominios de aislamiento. Como Swift puede mover código entre hilos y no se puede predecir en cuál reanudará, es necesario garantizar que los datos compartidos entre dominios son seguros de transferir.&lt;/p&gt;

&lt;h3&gt;
  
  
  Según el artículo, ¿cuáles son los tres problemas que evita dejar que Swift gestione los hilos?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uso excesivo de memoria (para guardar el contexto)&lt;/li&gt;
&lt;li&gt;Uso elevado de procesador (para cambiar de contexto)&lt;/li&gt;
&lt;li&gt;Inversión de prioridad&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  En el ejemplo de código, ¿por qué la "&lt;code&gt;Task&lt;/code&gt; 1" aparece ejecutándose en hilos distintos al inicio y al reanudarse?
&lt;/h3&gt;

&lt;p&gt;La creación de una &lt;code&gt;Task&lt;/code&gt; no garantiza la ejecución en un hilo específico. En el ejemplo, ante la aparición del punto de suspensión, la &lt;code&gt;Task&lt;/code&gt; 1 cambió de hilo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recitación
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Con tus propias palabras, ¿qué significa pensar en dominios de aislamiento en lugar de hilos?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Explica por qué Sendable se vuelve necesario precisamente porque Swift puede mover trabajo entre hilos.
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué cambio mental fundamental propone el artículo respecto a cómo escribir código concurrente en Swift?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cómo conectan entre sí los conceptos de actores, prioridades y Sendable dentro del modelo de Swift Concurrency?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] Relación entre Hilos y Tasks</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Tue, 28 Apr 2026 11:47:54 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-relacion-entre-hilos-y-tasks-3n2m</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-relacion-entre-hilos-y-tasks-3n2m</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es exactamente un hilo y por qué tiene un alto costo de creación y cambio de contexto?
&lt;/h3&gt;

&lt;p&gt;Un hilo es un recurso, manejado por el sistema operativo, que ejecuta una secuencia de instrucciones. Crear hilos y cambiar el contexto entre ellos es una operación muy costosa.&lt;/p&gt;

&lt;p&gt;Cada hilo requiere su propia pila de memoria (stack) y el cambio de contexto obliga al CPU a guardar y restaurar el estado completo del hilo (registros, puntero de instrucción, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué Swift Concurrency no garantiza en qué hilo se ejecutará una función asíncrona?
&lt;/h3&gt;

&lt;p&gt;Swift Concurrency dispone de un pool global concurrente de hilos (tantos como el número de procesadores del dispositivo).&lt;/p&gt;

&lt;p&gt;Para optimizar el uso de hilos, se despacha una &lt;code&gt;Task&lt;/code&gt; en cualquier hilo disponible. Cuando hay un punto de suspensión (&lt;code&gt;await&lt;/code&gt;), el runtime de Swift Concurrency cede el hilo a cualquier otra tarea. Luego, cuando la &lt;code&gt;Task&lt;/code&gt; recupera el contexto, el runtime de SC le asigna cualquier hilo disponible - que puede ser el que tenía inicialmente, pero no está garantizado, porque el sistema pudo haberlo asignado a otra &lt;code&gt;Task&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Aquí quien limita los hilos no es el sistema operativo sino el framework Swift Concurrency. El sistema operativo podría crear muchos más hilos (como lo hacía GCD). Es una decisión de diseño del framework, no una restricción del sistema operativo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué ocurre exactamente cuando una tarea llega a un punto de suspensión con &lt;code&gt;await&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;El sistema &lt;strong&gt;suspende&lt;/strong&gt; la &lt;code&gt;Task&lt;/code&gt; y devuelve el hilo al pool global de hilos - Lo que significa que está disponible para que cualquier otra &lt;code&gt;Task&lt;/code&gt; lo tome.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo funciona el &lt;code&gt;cooperative thread pool&lt;/code&gt; y por qué limita los hilos al número de núcleos de CPU?
&lt;/h3&gt;

&lt;p&gt;Para no tener "thread explosion" y así degradar el desempeño de la aplicación debido al cambio de contexto entre hilos  y posibles problemas de inversión de prioridades, el sistema operativo limita la creación de hilos al número de núcleos del procesador.&lt;/p&gt;

&lt;p&gt;El "cooperative thread pool" son todos los hilos disponibles para ser usados por las distintas &lt;code&gt;Task&lt;/code&gt;s.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es el &lt;code&gt;thread explosion&lt;/code&gt; y cómo lo evita Swift Concurrency?
&lt;/h3&gt;

&lt;p&gt;"thread explosion" ocurre porque se crean demasiados hilos y aparecen bloqueos que provocan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Desperdicio de memoria debido a los hilos detenidos.&lt;/li&gt;
&lt;li&gt;Intercambio excesivo de contexto (que reduce la eficiencia del procesador)&lt;/li&gt;
&lt;li&gt;Problemas de inversión de prioridad.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ¿Por qué tener menos hilos no reduce el rendimiento comparado con GCD?
&lt;/h3&gt;

&lt;p&gt;Aunque es contraintuitivo, el intercambio innecesario de contexto y el desperdicio de memoria son problemas que se reducen al tener menos hilos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué demuestra el ejemplo de código con &lt;code&gt;ThreadingDemonstrator&lt;/code&gt; sobre la relación entre tareas e hilos?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ThreadingDemonstrator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;firstTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task 1 started on thread: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="kt"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentThread&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task 1 resumed on thread: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="kt"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentThread&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;secondTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task 2 started on thread: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="kt"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;currentThread&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;demonstrate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;firstTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;secondTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ThreadingDemonstratorTests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;@Test&lt;/span&gt;
  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ThreadingDemonstrator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;sut&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;demonstrate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;No se puede garantizar el orden de ejecución de las tareas &lt;code&gt;firstTask&lt;/code&gt; y &lt;code&gt;secondTask&lt;/code&gt;. Para hacerlo hay que usar &lt;code&gt;await&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cuando se asigna un hilo a una tarea y esta se suspende, no se puede garantizar que lo recupere una vez se reanude.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ¿Por qué la tarea 1 puede reanudarse en un hilo diferente al que inició?
&lt;/h3&gt;

&lt;p&gt;Cuando se suspende la tarea 1, cede ("yield") el hilo que tenía y el sistema operativo es libre de asignárselo a cualquier otra tarea.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia introduce el modo Swift 6 respecto a acceder a &lt;code&gt;Thread.current&lt;/code&gt; y cómo se resuelve?
&lt;/h3&gt;

&lt;p&gt;Usar &lt;code&gt;Thread.current&lt;/code&gt; desde un contexto asíncrono arrojará el error de compilación: &lt;code&gt;Class property 'current' is unavailable from asynchronous contexts; Thread.current cannot be used from async contexts.&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La solución fue envolver el llamado de &lt;code&gt;Thread.current&lt;/code&gt; en un método (variable computada) &lt;code&gt;nonisolated static&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;nonisolated&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;currentThread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Thread&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Recitación
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Explica con tus propias palabras qué significa "ceder el hilo" (yielding the thread) cuando se usa await.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuáles son los tres conceptos erróneos sobre Swift Concurrency que menciona el artículo? ¿Puedes refutarlos?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué tres consecuencias negativas produce el thread explosion en GCD?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cómo describirías el cooperative thread pool a alguien sin experiencia en concurrencia?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿En qué situaciones concretas deberías seguir pensando en si algo corre en el hilo principal o en un hilo en segundo plano?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Si Swift Concurrency ya gestiona los hilos automáticamente, ¿qué valor tiene entender cómo funcionan internamente?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cómo cambiaría tu forma de escribir código asíncrono ahora que sabes que &lt;code&gt;await&lt;/code&gt; no bloquea el hilo?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué preguntas te quedan sin responder sobre el &lt;code&gt;@MainActor&lt;/code&gt; y cómo encaja con lo aprendido aquí?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] ¿Cuándo usar AsyncStream en lugar de AsyncSequence?</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Tue, 28 Apr 2026 10:59:43 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-58j0</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-58j0</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuándo debería usar &lt;code&gt;AsyncSequence&lt;/code&gt; en lugar de &lt;code&gt;AsyncStream&lt;/code&gt;, y viceversa?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/Swift/AsyncSequence" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncSequence&lt;/code&gt;&lt;/a&gt; es la abstracción a la que debería acoplarme, mientras que &lt;a href="https://developer.apple.com/documentation/swift/asyncstream" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncStream&lt;/code&gt;&lt;/a&gt; es una implementación concreta de &lt;code&gt;AsyncSequence&lt;/code&gt; que puedo utilizar para emitir eventos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué ventajas ofrece &lt;code&gt;AsyncStream&lt;/code&gt; para casos de uso comunes?
&lt;/h3&gt;

&lt;p&gt;Se puede usar directamente esta implementación concreta, definiendo el closure que recibe un &lt;code&gt;continuation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El API de &lt;code&gt;AsyncStream&lt;/code&gt; es fácil de recordar y escribir, y especialmente útil para crear puentes entre delegados, llamados a closures y emisión manual de eventos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se relacionan &lt;code&gt;AsyncSequence&lt;/code&gt; y &lt;code&gt;AsyncStream&lt;/code&gt; entre sí?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;AsyncStream&lt;/code&gt; conforma &lt;code&gt;AsyncSequence&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué ejemplo concreto usa el artículo para ilustrar el puente de delegates con &lt;code&gt;AsyncThrowingStream&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;En el artículo se creó un &lt;code&gt;LocationMonitor&lt;/code&gt; que funciona como delegado (&lt;code&gt;CLLocationManagerDelegate&lt;/code&gt;) de un &lt;code&gt;CLLocationManager&lt;/code&gt;. Este &lt;code&gt;LocationMonitor&lt;/code&gt; tenía un atributo llamado &lt;code&gt;stream&lt;/code&gt; de tipo &lt;code&gt;AsyncThrowingStream&amp;lt;CLLocation, Error&amp;gt;&lt;/code&gt;, manejado con un &lt;code&gt;continuation&lt;/code&gt; de tipo &lt;code&gt;AsyncThrowingStream&amp;lt;CLLocation, Error&amp;gt;.Continuation?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cada vez que el &lt;code&gt;LocationMonitor&lt;/code&gt; recibía un evento como delegado de &lt;code&gt;LocationMonitor&lt;/code&gt;, emitía un evento al &lt;code&gt;stream&lt;/code&gt; a través del &lt;code&gt;continuation&lt;/code&gt; con &lt;a href="https://developer.apple.com/documentation/swift/asyncthrowingstream/continuation/yield(_:)" rel="noopener noreferrer"&gt;&lt;code&gt;yield(_:)&lt;/code&gt;&lt;/a&gt;, y &lt;a href="https://developer.apple.com/documentation/swift/asyncthrowingstream/continuation/finish(throwing:)" rel="noopener noreferrer"&gt;&lt;code&gt;finish(throwing:)&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo funciona el método &lt;code&gt;AsyncStream.init(unfolding:oncancel:)&lt;/code&gt; en el ejemplo del servicio de &lt;code&gt;ping&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/init(unfolding:oncancel:)" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncStream.init(unfolding:onCancel:)&lt;/code&gt;&lt;/a&gt; recibe un closure asíncrono que produce elementos (&lt;code&gt;unfolding&lt;/code&gt;) y otro opcional que se maneja la cancelación (&lt;code&gt;oncancel&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué el artículo compara &lt;code&gt;AsyncSequence&lt;/code&gt; con el protocolo &lt;code&gt;Sequence&lt;/code&gt; en Swift?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;AsyncSequence&lt;/code&gt; es la versión asíncrona de &lt;code&gt;Sequence&lt;/code&gt;. Además, el artículo menciona que muy pocas veces implementamos el protocolo &lt;code&gt;Sequence&lt;/code&gt;, sino que son mayormente otros tipos de datos del SDK de iOS que lo conforman - Básicamente nosotros como desarrolladores tendríamos la misma relación con &lt;code&gt;AsyncSequence&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recitación / comprensión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sin releer, ¿puedes explicar con tus palabras cuándo elegirías &lt;code&gt;AsyncStream&lt;/code&gt; sobre &lt;code&gt;AsyncSequence&lt;/code&gt;?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué hace la &lt;code&gt;continuation&lt;/code&gt; en el ejemplo de &lt;code&gt;LocationMonitor&lt;/code&gt; y por qué es clave?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué APIs estándar de Apple mencionadas en el artículo conforman &lt;code&gt;AsyncSequence&lt;/code&gt;?
&lt;/h3&gt;




&lt;h3&gt;
  
  
  Repaso final
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la conclusión principal del artículo sobre cuál opción usar en la mayoría de proyectos reales?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué limitación menciona el artículo sobre el ejemplo de &lt;code&gt;LocationMonitor&lt;/code&gt;?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿En qué escenarios reales, mencionados explícitamente, tiene más sentido usar &lt;code&gt;AsyncStream&lt;/code&gt;?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] AsyncStream y AsyncThrowingStream</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Tue, 28 Apr 2026 01:33:44 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-asyncstream-y-asyncthrowingstream-i9</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-asyncstream-y-asyncthrowingstream-i9</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es un &lt;code&gt;AsyncStream&lt;/code&gt; y en qué se diferencia de un &lt;code&gt;AsyncThrowingStream&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Un &lt;code&gt;AsyncStream&lt;/code&gt; es un &lt;code&gt;AsyncSequence&lt;/code&gt; que puede emitir eventos de progreso y fin con base en un &lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncStream.Continuation&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Es muy parecido a un &lt;code&gt;Publisher&lt;/code&gt; de Combine, con la diferencia que solo admite un suscriptor.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AsyncThrowingStream&lt;/code&gt; es la versión que arroja error de &lt;code&gt;AsyncStream&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué podría querer reemplazar un closure de progreso/completación con un &lt;code&gt;AsyncThrowingStream&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Facilita la integración del API de &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; en lugar de una integración basada en closures. Además, &lt;code&gt;AsyncStream&lt;/code&gt; permite poder iterar con &lt;code&gt;for try await&lt;/code&gt; en lugar de anidar closures, lo que hace el flujo más lineal y legible.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué sucede si no se llama a &lt;code&gt;continuation.finish()&lt;/code&gt; al terminar un &lt;code&gt;stream&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;La implementación se va a quedar colgada sin terminar. El código que itera el stream con &lt;code&gt;for try await&lt;/code&gt; nunca avanza más allá del loop porque el stream nunca emite el evento de terminación.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué son las &lt;code&gt;buffer policies&lt;/code&gt; y cuándo tendría sentido usar cada una?
&lt;/h3&gt;

&lt;p&gt;Las "buffer policies" define qué hacer con los valores emitidos cuando no hay ningún consjmidor leyendo aún. Es decir: regulan el buffer previo a la lecutra, no a la entrega en tiempo real. En el artículo se mencionan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation/bufferingpolicy/unbounded" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncStream.Continuation.BufferingPolicy.unbounded&lt;/code&gt;&lt;/a&gt;: El suscriptor recibe todos los eventos pasados emitidos por el &lt;code&gt;AsyncStream&lt;/code&gt; antes de la suscripción.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation/bufferingpolicy/bufferingoldest(_:)" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncStream.Continuation.BufferingPolicy.bufferingOldest(_:)&lt;/code&gt;&lt;/a&gt;: El suscriptor recibe los primeros (oldest) &lt;code&gt;n&lt;/code&gt; eventos emitidos por el &lt;code&gt;AsyncStream&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation/bufferingpolicy/bufferingnewest(_:)" rel="noopener noreferrer"&gt;AsyncStream.Continuation.BufferingPolicy.bufferingNewest(_:)&lt;/a&gt;: El suscriptor recibe los últimos (newest) &lt;code&gt;n&lt;/code&gt; eventos emitidos por el &lt;code&gt;AsyncStream&lt;/code&gt;. En el artículo ponen de ejemplo que al usar &lt;code&gt;bufferingnewest(0)&lt;/code&gt;, se ignoran todos los eventos pasados emitidos por el &lt;code&gt;AsyncStream&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ¿En qué se diferencia un &lt;code&gt;AsyncStream&lt;/code&gt; de un &lt;code&gt;publisher&lt;/code&gt; de &lt;code&gt;Combine&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;El &lt;code&gt;Publisher&lt;/code&gt; de Combine puede tener varios suscriptores. El &lt;code&gt;AsyncStream&lt;/code&gt; solo puede tener uno.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se usa el &lt;code&gt;continuation&lt;/code&gt; para enviar valores, manejar errores y terminar el &lt;code&gt;stream&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Sobre el &lt;code&gt;continuation&lt;/code&gt; se pueden usar los siguientes métodos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation/yield(with:)" rel="noopener noreferrer"&gt;&lt;code&gt;yield(with:)&lt;/code&gt;&lt;/a&gt;: Para emitir un elemento de tipo &lt;code&gt;Result&amp;lt;Element,Never&amp;gt; en un&lt;/code&gt;AsyncStream`.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncthrowingstream/continuation/yield(with:)" rel="noopener noreferrer"&gt;&lt;code&gt;yield(with:)&lt;/code&gt;&lt;/a&gt;: Para emitir un elemento de tipo &lt;code&gt;Result&amp;lt;Element,Failure&amp;gt; en un &lt;/code&gt;AsyncThrowingStream`.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation/finish()" rel="noopener noreferrer"&gt;&lt;code&gt;finish()&lt;/code&gt;&lt;/a&gt;: Para cerrar el Stream sin emitir error.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncthrowingstream/continuation/finish(throwing:)" rel="noopener noreferrer"&gt;&lt;code&gt;finish(throwing:)&lt;/code&gt;&lt;/a&gt;: Para cerrar el Stream emitiendo un error&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncstream/continuation/ontermination" rel="noopener noreferrer"&gt;&lt;code&gt;onTermination&lt;/code&gt;&lt;/a&gt;: Suscribe un closure para ejecutar algún trabajo cuando termina el stream. Este sirve para hacer labores de limpieza o depuración.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ¿Qué hace el &lt;code&gt;callback onTermination&lt;/code&gt; y para qué casos de uso es útil?
&lt;/h3&gt;

&lt;p&gt;Suscribe un closure para ejecutar algún trabajo cuando termina el stream. Este sirve para hacer labores de limpieza o depuración.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo y cuándo se cancela un stream, y qué efecto tiene la cancelación?
&lt;/h3&gt;

&lt;p&gt;Un Stream se cancela cuando el contexto asíncrono que lo envuelve es cancelado (e.g. &lt;code&gt;Task.cancel()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;El stream se termina (no en error, ni en success), sino que se invoca &lt;code&gt;onTermination&lt;/code&gt; con la causa (i.e. "termination reason: cancelled")&lt;/p&gt;

&lt;p&gt;No hay forma de cancelar el stream explícitamente, solo de forma indirectamente a través del &lt;code&gt;Task&lt;/code&gt; que lo envuelve.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué no es seguro tener múltiples consumidores de un mismo &lt;code&gt;AsyncStream&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Como solo puede tener un suscriptor, no se sabe a cuál le va a entregar el valor. Los valroes se reparten entre los consumidores en lugar de duplicarse - Cada valor lo recibe uno solo, de forma impredecible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recordar sin mirar el texto
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Explica con tus propias palabras el ciclo de vida de un &lt;code&gt;AsyncThrowingStream&lt;/code&gt;, desde su creación hasta su terminación.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuáles son las tres razones posibles por las que un stream puede terminar y cómo se reporta cada una?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Sin mirar el código, describe cómo transformarías el &lt;code&gt;FileDownloader&lt;/code&gt; basado en closures a uno basado en &lt;code&gt;AsyncThrowingStream&lt;/code&gt;.
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión y conexión de ideas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿En qué escenarios concretos de tu propio código usarías un &lt;code&gt;AsyncStream&lt;/code&gt; en lugar de &lt;code&gt;Combine&lt;/code&gt; o callbacks?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la limitación más importante de &lt;code&gt;AsyncStream&lt;/code&gt; mencionada en el artículo y cómo se puede mitigar?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué errores de programación comunes advierte el artículo y qué estrategias propone para detectarlos?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] Trabajando con secuencias asíncronas</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Mon, 27 Apr 2026 23:31:04 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-trabajando-con-secuencias-asincronas-3ego</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-trabajando-con-secuencias-asincronas-3ego</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es un &lt;code&gt;AsyncSequence&lt;/code&gt; y en qué se diferencia de un &lt;code&gt;Sequence&lt;/code&gt; normal?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/Swift/AsyncSequence" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncSequence&lt;/code&gt;&lt;/a&gt; es un tipo de dato que provee acceso secuencial e iterativo a una colección de forma asíncrona.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AsyncSequence&lt;/code&gt; es un hermano de &lt;code&gt;Sequence&lt;/code&gt; que prácticamente puede hacer todo lo que hace &lt;code&gt;Sequence&lt;/code&gt; (como &lt;a href="https://developer.apple.com/documentation/swift/asyncsequence/contains(_:)" rel="noopener noreferrer"&gt;&lt;code&gt;contains(_:)&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.apple.com/documentation/swift/asyncsequence/map(_:)-1q1k3" rel="noopener noreferrer"&gt;&lt;code&gt;map(_:)&lt;/code&gt;&lt;/a&gt;) con la diferencia que los datos se recorren de forma asíncrona.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué rol cumplen &lt;code&gt;AsyncIterator&lt;/code&gt; y el método &lt;code&gt;next()&lt;/code&gt; dentro de una secuencia asíncrona?
&lt;/h3&gt;

&lt;p&gt;Un tipo de dato que conforme el protocolo &lt;code&gt;AsyncSequence&lt;/code&gt; debe definir el método &lt;a href="https://developer.apple.com/documentation/swift/asyncsequence/makeasynciterator()" rel="noopener noreferrer"&gt;&lt;code&gt;makeAsyncIterator()&lt;/code&gt;&lt;/a&gt; que devuelve una instancia que conforme el protocolo &lt;a href="https://developer.apple.com/documentation/swift/asynciteratorprotocol" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncIteratorProtocol&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Un &lt;code&gt;AsyncIterator&lt;/code&gt; es como un &lt;a href="https://developer.apple.com/documentation/swift/iteratorprotocol" rel="noopener noreferrer"&gt;&lt;code&gt;IteratorProtocol&lt;/code&gt;&lt;/a&gt; con la diferencia que debe recorrer una colección asíncrona a través del método &lt;a href="https://developer.apple.com/documentation/swift/asynciteratorprotocol/next()" rel="noopener noreferrer"&gt;&lt;code&gt;next() async&lt;/code&gt;&lt;/a&gt; que puede tener puntos de suspensión y, retorna el siguiente valor de la colección o &lt;code&gt;nil&lt;/code&gt; si ya terminó el trabajo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se indica el fin de la iteración en un &lt;code&gt;AsyncSequence&lt;/code&gt; personalizado?
&lt;/h3&gt;

&lt;p&gt;Se indica el fin de una iteración devolviendo &lt;code&gt;nil&lt;/code&gt;. Esto puede ocurrir por dos razones:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;se alcanzó el límite configurado&lt;/li&gt;
&lt;li&gt;la tarea fue cancelada (&lt;code&gt;Task.isCancelled&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ¿Por qué se recomienda usar &lt;code&gt;AsyncStream&lt;/code&gt; en lugar de implementar &lt;code&gt;AsyncSequence&lt;/code&gt; directamente?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://developer.apple.com/documentation/swift/asyncstream" rel="noopener noreferrer"&gt;&lt;code&gt;AsyncStream&lt;/code&gt;&lt;/a&gt; es más conveniente de configurar que &lt;code&gt;AsyncSequence&lt;/code&gt;, porque al usar este último se debe un &lt;code&gt;AsyncIterator&lt;/code&gt; y manejar su estado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué operadores de &lt;code&gt;Sequence&lt;/code&gt; están disponibles también para secuencias asíncronas?
&lt;/h3&gt;

&lt;p&gt;Métodos como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.apple.com/documentation/swift/asyncsequence/contains(where:)" rel="noopener noreferrer"&gt;&lt;code&gt;contains(where:)&lt;/code&gt;&lt;/a&gt; - Tener cuidado que métodos como este esperan a que la secuencia asíncrona termine de emitir elementos y se puede quedar esperando indefinidamente.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/swift/asyncsequence/map(_:)-70wgb" rel="noopener noreferrer"&gt;&lt;code&gt;map(_:)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/swift/asyncsequence/filter(_:)-435af" rel="noopener noreferrer"&gt;&lt;code&gt;filter(_:)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Identifica cómo el protocolo &lt;code&gt;AsyncSequence&lt;/code&gt; define el acceso a valores sin generarlos por sí mismo.
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;AsyncSequence&lt;/code&gt; se encarga de la construcción del &lt;code&gt;AsyncIteratorProtocol&lt;/code&gt;, quien técnicamente es el encargado de generar los elementos en el método &lt;code&gt;next() async&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analiza cómo la cancelación con &lt;code&gt;Task.isCancelled&lt;/code&gt; interactúa con el ciclo de vida de la secuencia.
&lt;/h3&gt;

&lt;p&gt;Entro del contexto de &lt;a href="https://developer.apple.com/documentation/swift/asynciteratorprotocol/next()" rel="noopener noreferrer"&gt;&lt;code&gt;next() async&lt;/code&gt;&lt;/a&gt; es &lt;strong&gt;de vital importancia&lt;/strong&gt; verificar que la tarea no haya sido cancelada con &lt;code&gt;Task.isCancelled&lt;/code&gt; (sin esta verificación, la secuencia seguiría emitiendo valores a pesar de que la tarea hubiera sido cancelada). Si lo fue, entonces retornar &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recitación
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Explica con tus palabras qué hace el método &lt;code&gt;next()&lt;/code&gt; en el ejemplo &lt;code&gt;Counter&lt;/code&gt;.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cómo se usa &lt;code&gt;for await&lt;/code&gt; para iterar sobre un &lt;code&gt;AsyncSequence&lt;/code&gt; y por qué es necesario el &lt;code&gt;await&lt;/code&gt;?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Menciona al menos dos operadores que se pueden aplicar sobre una secuencia asíncrona y describe su efecto.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué ocurre si una secuencia asíncrona nunca termina y usas un método como &lt;code&gt;contains&lt;/code&gt;?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Revisión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿En qué situaciones reales tiene sentido usar un &lt;code&gt;AsyncSequence&lt;/code&gt; en lugar de un &lt;code&gt;array&lt;/code&gt; estático?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Por qué el artículo dice que un &lt;code&gt;AsyncSequence&lt;/code&gt; "prepara para valores asíncronos" aunque no siempre los envíe de forma asíncrona?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué relación existe entre los task groups vistos en lecciones anteriores y el concepto de &lt;code&gt;AsyncSequence&lt;/code&gt;?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Después de leer este módulo, ¿qué preguntas tienes sobre &lt;code&gt;AsyncStream&lt;/code&gt;, el siguiente tema?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
    <item>
      <title>[SC] Usando un Mutex como alternativa a los actores</title>
      <dc:creator>GoyesDev</dc:creator>
      <pubDate>Mon, 27 Apr 2026 21:29:37 +0000</pubDate>
      <link>https://forem.com/david_goyes_a488f58a17a53/sc-usando-un-mutex-como-alternativa-a-los-actores-18bo</link>
      <guid>https://forem.com/david_goyes_a488f58a17a53/sc-usando-un-mutex-como-alternativa-a-los-actores-18bo</guid>
      <description>&lt;h2&gt;
  
  
  Preguntas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es un &lt;code&gt;Mutex&lt;/code&gt; y en qué se diferencia de un &lt;code&gt;Lock&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Un &lt;code&gt;Mutex&lt;/code&gt; es un tipo de &lt;code&gt;Lock&lt;/code&gt; del framework &lt;a href="https://developer.apple.com/documentation/synchronization" rel="noopener noreferrer"&gt;&lt;code&gt;Synchronization&lt;/code&gt;&lt;/a&gt; usado para sincronizar accesos a una variable a través del método &lt;a href="https://developer.apple.com/documentation/synchronization/mutex/withlock(_:)" rel="noopener noreferrer"&gt;&lt;code&gt;withLock(_:)&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;El método &lt;code&gt;withLock&lt;/code&gt; es equivalente a hacer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observar que &lt;code&gt;value&lt;/code&gt; es un valor &lt;code&gt;inout&lt;/code&gt;, que se devuelve el valor generado por &lt;code&gt;try body(&amp;amp;value)&lt;/code&gt; y que puede arrojar un error.&lt;/p&gt;

&lt;p&gt;La diferencia importante entre &lt;code&gt;Mutex&lt;/code&gt; y &lt;code&gt;Lock&lt;/code&gt; es que usando &lt;code&gt;Lock&lt;/code&gt;, el tipo de dato no es &lt;code&gt;Sendable&lt;/code&gt; (tendría que marcarse con &lt;code&gt;@unchecked Sendable&lt;/code&gt;). En cambio, &lt;code&gt;Mutex&lt;/code&gt; sí es &lt;code&gt;Sendable&lt;/code&gt; porque encapsula su valor internamente y controla todo acceso a él.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué Apple introdujo un &lt;code&gt;Mutex&lt;/code&gt; si ya existen los actores en Swift Concurrency?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Mutex&lt;/code&gt; es una aproximación bloqueante síncrona que, en ocasiones, puede servir en lugar de un &lt;code&gt;actor&lt;/code&gt; asíncrono. Usar el actor asíncrono implica un "overhead" de "scheduling", además de que el invocador debe estar en un contexto síncrono.&lt;/p&gt;

&lt;p&gt;El &lt;code&gt;Mutex&lt;/code&gt; es útil cuando el trabajo protegido es breve y el bloqueo es más eficiente que suspender y reanudar una tarea.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Desde qué versiones de iOS y macOS está disponible el framework &lt;code&gt;Synchronization&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;iOS 18 y macOS 15.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se usa el método &lt;code&gt;withLock&lt;/code&gt; y qué tipo de acceso proporciona al valor protegido?
&lt;/h3&gt;

&lt;p&gt;Debido a que el parámetro que recibe &lt;code&gt;withLock&lt;/code&gt; es &lt;code&gt;inout&lt;/code&gt;, entonces da un acceso por referencia.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withLock&lt;/code&gt; se usa pasando un closure que puede modificar el valor protegido y puede retornar algún valor. En el ejemplo del artículo teníamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;currentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withLock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;currentCount&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;currentCount&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withLock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;currentCount&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="n"&gt;currentCount&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ¿Cómo permite el &lt;code&gt;Mutex&lt;/code&gt; trabajar con tipos no-&lt;code&gt;Sendable&lt;/code&gt; como &lt;code&gt;NSBezierPath&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;A pesar de que &lt;code&gt;NSBezierPath&lt;/code&gt; es no-&lt;code&gt;Sendable&lt;/code&gt;, se puede crear un &lt;code&gt;Mutex&lt;/code&gt;, constante (&lt;code&gt;let&lt;/code&gt;), que envuelva al &lt;code&gt;NSBezierPath&lt;/code&gt; y modificar el path protegido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Mutex&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;NSBezierPath&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;NSBezierPath&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;storeTouch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;point&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NSPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withLock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ¿Qué sucede cuando múltiples hilos intentan adquirir un &lt;code&gt;Mutex&lt;/code&gt; al mismo tiempo?
&lt;/h3&gt;

&lt;p&gt;Si un hilo trata de tomar el &lt;code&gt;Mutex&lt;/code&gt; y este ya fue tomado, entonces el hilo permanece bloqueado hasta que el &lt;code&gt;Mutex&lt;/code&gt; sea liberado.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recapitulación
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿En qué situaciones concretas es preferible usar un &lt;code&gt;Mutex&lt;/code&gt; en lugar de un actor?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Cómo se puede lanzar un error desde dentro del closure &lt;code&gt;withLock&lt;/code&gt;?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Repaso y reflexión
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la conclusión principal del artículo respecto a la elección entre actores y &lt;code&gt;Mutex&lt;/code&gt;?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  ¿Qué ventajas y desventajas tiene cada herramienta según el contexto del proyecto?
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Bibliografía
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://courses.avanderlee.com/p/swift-concurrency" rel="noopener noreferrer"&gt;Van der Lee, A. (2025). &lt;em&gt;Swift Concurrency Course&lt;/em&gt; [Curso en línea]. avanderlee.com.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>swift</category>
      <category>ios</category>
      <category>concurrency</category>
      <category>swiftconcurrency</category>
    </item>
  </channel>
</rss>
