Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Kit de desarrollo de software de Swift

Swift Concurrency - Swift SDK

Swift's concurrency system provides built-in support for writing asynchronous and parallel code in a structured way. For a detailed overview of the Swift concurrency system, refer to the Swift Programming Language Concurrency topic.

While the considerations on this page broadly apply to using realm with Swift concurrency features, Realm Swift SDK version 10.39.0 adds support for using Realm with Swift Actors. You can use Realm isolated to a single actor or use Realm across actors.

Realm's actor support simplifies using Realm in a MainActor and background actor context, and supersedes much of the advice on this page regarding concurrency considerations. For more information, refer to Use Realm with Actors - Swift SDK.

As you implement concurrency features in your app, consider this caveat about Realm's threading model and Swift concurrency threading behaviors.

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.

As a general rule, keep in mind that using Realm in an await context without incorporating threading protection may yield inconsistent behavior. Sometimes, the code may succeed. In other cases, it may throw an error related to writing on an incorrect thread.

Many Realm Swift APIs that involve working with an Atlas App Services app or a synchronized realm are compatible with Swift's async/await syntax. For examples, check out:

Si tienes solicitudes de funcionalidades específicas relacionadas con las APIs asíncronas/await de Swift, consulta el Motor de opiniones MongoDB para Realm. El equipo de Realm Swift SDK planea continuar desarrollando funcionalidades relacionadas con la concurrencia basándose en la retroalimentación de la comunidad y en la evolución de la concurrencia de 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 has two APIs that allow for performing asynchronous writes:

Ambas APIs te permiten añadir, actualizar o borrar objetos en segundo plano sin utilizar objetos congelados o pasar una referencia segura para hilos.

With the writeAsync() API, waiting to obtain the write lock and committing a transaction occur in the background. The write block itself runs on the calling thread. This provides thread-safety without requiring you to manually handle frozen objects or passing references across threads.

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.

The asyncWrite() API suspends the calling task while waiting for its turn to write rather than blocking the thread. In addition, the actual I/O to write data to disk is done by a background worker thread. For small writes, using this function on the main thread may block the main thread for less time than manually dispatching the write to a background thread.

For more information, including code examples, refer to: Perform a Background Write.

Swift concurrency provides APIs to manage Tasks and TaskGroups. The Swift concurrency documentation defines a task as a unit of work that can be run asynchronously as part of your program. Task allows you to specificially define a unit of asynchronous work. TaskGroup lets you define a collection of Tasks to execute as a unit under the parent TaskGroup.

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.

However, the thread-confined constraints described in Suspending Execution with Await above apply in the Task context. If your Task contains await points, subsequent code might run or resume on a different thread and violate Realm's thread confinement.

You must annotate functions that you run in a Task context with @MainActor to ensure code that accesses Realm only runs on the main thread. This negates some of the benefits of using Tasks, and may mean this is not a good design choice for apps that use Realm unless you are using Tasks solely for networking activities like managing users.

Tip

Use Realm with Swift Actors

The information in this section is applicable to Realm SDK versions earlier than 10.39.0. Starting in Realm Swift SDK version 10.39.0 and newer, the SDK supports using Realm with Swift Actors and related async functionality.

For more information, refer to Use Realm with Actors - Swift SDK.

Actor isolation provides the perception of confining Realm access to a dedicated actor, and therefore seems like a safe way to manage Realm access in an asynchronous context.

However, using Realm in a non-@MainActor async function is currently not supported.

En Swift 5.6, esto a menudo funcionaba por casualidad. La ejecución después de un await continuaría en cualquier hilo en el que se ejecutó lo que se esperaba. El uso de await Realm() en una función asíncrona haría que el código posterior se ejecute en el hilo principal hasta la siguiente llamada a una función aislada por un actor.

Swift 5.7 instead hops threads whenever changing actor isolation contexts. An unisolated async function always runs on a background thread instead.

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.

La mayoría de las veces, el error que ves relacionado con el acceso a Realm a través de código concurrente es Realm accessed from incorrect thread. Esto se debe a los problemas de aislamiento de hilos 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:

  • Actualiza a una versión del SDK de Realm Swift que admita realms aislados por actor y utiliza esto como una alternativa a la gestión manual de hilos. Para obtener más información, consulta Usar Realm con Actores - Swift SDK.

  • 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.

  • Apps that do not use actor-isolated realms can use the writeAsync API to perform a background write. This manages realm access in a thread-safe way without requiring you to write specialized code to do it yourself. This is a special API that outsources aspects of the write process - where it is safe to do so - to run in an async context. Unless you are writing to an actor-isolated realm, you do not use this method with Swift's async/await syntax. Use this method synchronously in your code. Alternately, you can use the asyncWrite API with Swift's async/await syntax when awaiting writes to asynchronous realms.

  • If you want to explicitly write concurrency code that is not actor-isolated where accessing a realm is done in a thread-safe way, you can explicitly pass instances across threads where applicable to avoid threading-related crashes. This does require a good understanding of Realm's threading model, as well as being mindful of Swift concurrency threading behaviors.

The Realm Swift SDK public API contains types that fall into three broad categories:

  • Sendable

  • Not Sendable and not thread confined

  • Thread-confined

You can share types that are not Sendable and not thread confined between threads, but you must synchronize them.

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.

Sendable
Non-Sendable
Limitado a hilos

CualquierBSON

RLMAppConfiguration

AnyRealmCollection

AsyncOpen

RLMFindOneAndModifyOptions

AnyRealmValue

AsyncOpenSubscription

RLMFindOptions

Lista

RLMAPIKeyAuth

Transporte en red RLM

Map

Aplicación RLM

RLMRequest

MutableSet

RLMAsyncOpenTask

Respuesta de RLMR

Proyección

RLMChangeStream

Configuración de RLMSync

RLMArray

RLMCompensatingWriteInfo

RLMSyncTimeoutOptions

RLMChangeStream

RLMCredentials

RLMDictionary

RLMDecimal128

RLMDictionaryChange

RLMEmailPasswordAuth

RLMEmbeddedObject

RLMMaxKey

RLMLinkingObjects

RLMMinKey

RLMObject

RLMMongoClient

RLMPropertyChange

RLMMongoCollection

RLMRealm

RLMMongoDatabase

RLMResults

RLMObjectId

RLMSection

RLMObjectSchema

RLMSectionedResults

Notificación de progreso de RLM

RLMSectionedResultsChangeset

RLMProgressNotificationToken

Conjunto RLM

RLMProperty

RLMSyncSubscription

RLMPropertyDescriptor

RLMSyncSubscriptionSet

RLMProviderClient

RealmOptional

Cliente RLMPush

RealmProperty

RLMSchema

RLMSortDescriptor

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

RLMSyncManager

RLMSyncSession

RLMThreadSafeReference

RLMUpdateResult

RLMUser

RLMUserAPIKey

RLMUserIdentity

RLMUserProfile

ThreadSafe

Volver

Use Realm with Actors

En esta página