Docs Menu
Docs Home
/ /
Kit de desarrollo de software de Swift

Concurrencia de Swift - SDK de Swift

El sistema de concurrencia de Swift proporciona soporte integrado para escribir código asíncrono y paralelo de forma estructurada. Para obtener una descripción detallada del sistema de concurrencia de Swift, consulte Tema de concurrencia del lenguaje de programación Swift.

Si bien las consideraciones de esta página se aplican en general al uso de realm con funciones de concurrencia de Swift, la versión 10.39.0 del SDK de Realm Swift permite usar Realm con actores de Swift. Puede usar Realm de forma aislada para un solo actor o con varios actores.

La compatibilidad con actores de Realm simplifica su uso en un contexto de actor principal y actor en segundo plano, y reemplaza gran parte de las recomendaciones de esta página sobre consideraciones de concurrencia. Para más información, consulte Usar Realm con actores - Swift SDK.

A medida que implementa funciones de concurrencia en su aplicación, tenga en cuenta esta advertencia sobre el modelo de subprocesos de Realm y los comportamientos de subprocesos de concurrencia de Swift.

En cualquier lugar donde utilice la palabra clave Swift await Marca un posible punto de suspensión en la ejecución de tu código. Con Swift 5.7, una vez que tu código se suspende, el código subsiguiente podría no ejecutarse en el mismo hilo. Esto significa que, en cualquier momento que uses await en tu código, el código subsiguiente podría ejecutarse en un hilo diferente al del código anterior o posterior.

Esto es intrínsecamente incompatible con el paradigma de objetos activos de Realm. Los objetos activos, las colecciones y las instancias Realm están confinados a un hilo: es decir, sólo son válidos en el hilo en el que se crearon. En la práctica, esto significa que no puedes pasar instancias en vivo a otros hilos. Sin embargo, Realm ofrece varios mecanismos para el uso compartido de objetos entre hilos. Estos mecanismos suelen requerir que tu código realice algún manejo explícito para transferir datos de forma segura entre hilos.

Puede utilizar algunos de estos mecanismos, como objetos congelados o la ThreadSafeReference, para utilizar de forma segura objetos Realm e instancias entre hilos utilizando la palabra clave await. También puedes evitar problemas relacionados con la ejecución simultánea marcando cualquier código asíncrono de Realm con @MainActor para garantizar que tus aplicaciones siempre ejecuten este código en el hilo principal.

Como regla general, tenga en cuenta que usar Realm en un await contexto sin incorporar protección de subprocesos puede generar un comportamiento incoherente. En ocasiones, el código puede funcionar correctamente. En otros casos, puede generar un error relacionado con la escritura en un subproceso incorrecto.

Muchas API de Realm Swift que trabajan con una aplicación de Atlas App Services o un reino sincronizado son compatibles con la sintaxis async/await de Swift. Para ver ejemplos, consulte:

Si tiene solicitudes de funciones específicas relacionadas con las API async/await de Swift, consulte el motor de comentarios de MongoDB para Realm. El equipo del SDK de Swift de Realm planea seguir desarrollando funciones relacionadas con la concurrencia basándose en los comentarios de la comunidad y la evolución de la concurrencia en Swift.

Un caso de uso comúnmente solicitado para el código asíncrono es realizar operaciones de guardar en segundo plano sin bloquear el hilo principal.

Realm tiene dos API que permiten realizar escrituras asincrónicas:

Ambas API le permiten agregar, actualizar o eliminar objetos en segundo plano sin utilizar objetos congelados ni pasar una referencia segura para subprocesos.

Con la API writeAsync(), la espera para obtener el bloqueo de escritura y la confirmación de una transacción se realizan en segundo plano. El bloque de escritura se ejecuta en el hilo que realiza la llamada. Esto proporciona seguridad para subprocesos sin necesidad de gestionar manualmente objetos congelados ni pasar referencias entre subprocesos.

Sin embargo, mientras se ejecuta el bloque de escritura, se bloquean nuevas transacciones en el hilo que realiza la llamada. Esto significa que una escritura grande con la API writeAsync() podría bloquear escrituras pequeñas y rápidas durante su ejecución.

La API asyncWrite() suspende la tarea que realiza la llamada mientras espera su turno para escribir, en lugar de bloquear el hilo. Además, la E/S para escribir datos en el disco la realiza un hilo de trabajo en segundo plano. Para escrituras pequeñas, usar esta función en el hilo principal puede bloquearlo durante menos tiempo que enviar manualmente la escritura a un hilo en segundo plano.

Para obtener más información, incluidos ejemplos de código, consulte: Realizar una escritura en segundo plano.

La concurrencia de Swift proporciona API para gestionar tareas y grupos de tareas. La documentación de concurrencia de Swift define una tarea como una unidad de trabajo que puede ejecutarse asincrónicamente como parte de su programa. Tarea permite definir específicamente una unidad de trabajo asincrónico. Grupo de tareas permite definir un conjunto de tareas que se ejecutan como una unidad dentro del grupo de tareas principal.

Las tareas y los grupos de tareas permiten asignar el hilo a otras tareas importantes o cancelar una tarea de larga duración que podría bloquear otras operaciones. Para obtener estas ventajas, podrías considerar usar tareas y grupos de tareas para gestionar las escrituras en el dominio en segundo plano.

Sin embargo, las restricciones de hilo descritas en "Suspender la ejecución con Await" se aplican en el contexto de la tarea. Si la tarea contiene await puntos, el código posterior podría ejecutarse o reanudarse en un hilo diferente e infringir el confinamiento de hilo de Realm.

Debes anotar las funciones que ejecutas en un contexto de tarea con @MainActor para garantizar que el código que accede a Realm solo se ejecute en el hilo principal. Esto anula algunas de las ventajas de usar tareas y puede significar que no sea una buena opción de diseño para aplicaciones que usan Realm, a menos que las uses únicamente para actividades de red, como la gestión de usuarios.

Tip

Usar Realm con actores Swift

La información de esta sección se aplica a las versiones del SDK de Realm anteriores a la 10.39.0. A partir de la versión 10.39.0 del SDK de Realm Swift y posteriores, el SDK admite el uso de Realm con actores Swift y la funcionalidad asíncrona relacionada.

Para obtener más información, consulte Usar Realm con actores - Swift SDK.

El aislamiento de actores proporciona la percepción de limitar el acceso al Reino a un actor dedicado y, por lo tanto, parece una forma segura de gestionar el acceso al Reino en un contexto asincrónico.

Sin embargo, actualmente no se admite el uso de Realm en una función asíncrona que no sea@MainActor.

En Swift 5.6, esto solía funcionar por coincidencia. La ejecución después de un await continuaba en el hilo donde se ejecutaba el objeto esperado. Usar await Realm() en una función asíncrona hacía que el código posterior se ejecutara en el hilo principal hasta la siguiente llamada a una función aislada del actor.

Swift 5.7, en cambio, salta entre subprocesos al cambiar los contextos de aislamiento de los actores. Una función asíncrona no aislada siempre se ejecuta en un subproceso en segundo plano.

Si tienes código que utiliza await Realm() y funciona en la versión 5.6, marcar la función como @MainActor hará que funcione con Swift 5.7. Funcionará como lo hizo - sin querer - en 5.6.

Con mayor frecuencia, el error que ve relacionado con el acceso a Realm a través del código de concurrencia es Realm accessed from incorrect thread.. Esto se debe a los problemas de aislamiento de subprocesos que se describen en esta página.

Para evitar problemas relacionados con el threading en el código que utiliza funcionalidades de concurrencia de Swift:

  • Actualice a una versión del SDK de Realm Swift que admita dominios aislados por actores y úsela como alternativa a la gestión manual de subprocesos. Para obtener más información, consulte Usar Realm con actores - SDK de Swift.

  • No cambie los contextos de ejecución al acceder a un dominio. Si abre un dominio en el hilo principal para proporcionar datos a su interfaz de usuario, anote con @MainActor las funciones posteriores donde acceda al dominio de forma asíncrona para garantizar que siempre se ejecuten en el hilo principal. Recuerde que await marca un punto de suspensión que podría cambiar a otro hilo.

  • Las aplicaciones que no usan dominios aislados por actores pueden usar la writeAsync API para realizar una escritura en segundo plano. Esto gestiona el acceso al dominio de forma segura para subprocesos, sin necesidad de escribir código especializado. Esta API especial externaliza aspectos del proceso de escritura (cuando es seguro hacerlo) para ejecutarse en un contexto asíncrono. A menos que escriba en un dominio aislado por actores, no utilice este método con async/await la sintaxis de Swift. Úselo sincrónicamente en su código. Como alternativa, puede usar la asyncWrite API con la sintaxis de Swift async/await al esperar escrituras en dominios asíncronos.

  • Si desea escribir código concurrente explícito que no esté aislado de actores y donde el acceso a un reino se realice de forma segura para subprocesos, puede pasar instancias explícitamente entre subprocesos cuando corresponda para evitar fallos relacionados con los subprocesos. Esto requiere un buen conocimiento del modelo de subprocesos de Realm, así como la consideración de los comportamientos de subprocesos concurrentes de Swift.

La API pública del SDK Swift de Realm contiene tipos que se dividen en tres categorías amplias:

  • Enviable

  • No se puede enviar y no está confinado en el hilo

  • Confinado en hilo

Puedes compartir tipos que no sean Enviables y que no estén confinados entre subprocesos, pero debes sincronizarlos.

Los tipos confinados por subprocesos, a menos que estén congelados, se limitan a un contexto de aislamiento. No se pueden pasar entre estos contextos, ni siquiera con sincronización.

Enviable
No enviable
Hilo confinado

CualquierBSON

Configuración de RLMApp

AnyRealmCollection

AsyncOpen

Opciones de búsqueda y modificación de RLM

AnyRealmValue

Suscripción abierta asíncrona

Opciones de búsqueda de RLM

Lista

Autorización de clave RLMAPI

Transporte en red RLM

Map

Aplicación RLM

Solicitud RLM

MutableSet

RLMAsyncOpenTask

Respuesta de RLMR

Proyección

Flujo de cambio de RLM

Configuración de RLMSync

RLMArray

Información de escritura compensatoria RLM

Opciones de tiempo de espera de sincronización de RLM

Flujo de cambio de RLM

Credenciales de RLMC

Diccionario RLM

RLMDecimal128

Cambio de diccionario RLM

RLMEmailPasswordAuth

Objeto RLMEmbedded

RLMMaxKey

Objetos de enlace RLM

RLMMinKey

Objeto RLM

Cliente RLMMongo

Cambio de propiedad RLM

Colección RLMMongo

RLMRealm

Base de datos RLMMongo

Resultados de RLM

ID de objeto RLM

RLMSection

Esquema de objeto RLM

Resultados seccionados de RLM

Notificación de progreso de RLM

Conjunto de cambios de resultados seccionados de RLM

Token de notificación de progreso de RLM

Conjunto RLM

Propiedad RLM

Suscripción a RLMSync

Descriptor de propiedad RLM

Conjunto de suscripciones de sincronización RLM

Cliente proveedor de RLM

Reino Opcional

Cliente RLMPush

Propiedad del reino

Esquema RLMSchema

Descriptor de clasificación RLMSort

Token de acción de error de sincronización RLM

Administrador de sincronización RLM

Sesión de sincronización RLM

Referencia segura para subprocesos de RLM

Resultado de actualización de RLM

Usuario de RLMU

RLMUserAPIKey

Identidad de usuario de RLMU

Perfil de usuario de RLMU

ThreadSafe

Volver

Usar Realm con actores

En esta página