Docs Menu
Docs Home
/ /
CRUD

Subprocesos - Swift SDK

Para que tus apps de iOS y tvOS sean rápidas y responsivas, debes equilibrar el tiempo de procesamiento necesario para diseñar los elementos visuales y gestionar las interacciones del usuario con el tiempo necesario para procesar los datos y ejecutar la lógica de negocio. Normalmente, los desarrolladores de apps distribuyen este trabajo entre varios subprocesos: el subproceso principal o de interfaz de usuario para todo el trabajo relacionado con la interfaz de usuario, y uno o más subprocesos en segundo plano para procesar las cargas de trabajo más pesadas antes de enviarlas al subproceso de interfaz de usuario para su presentación. Al delegar el trabajo pesado a los subprocesos en segundo plano, el subproceso de interfaz de usuario puede mantener una alta capacidad de respuesta independientemente del tamaño de la carga de trabajo. Sin embargo, puede ser notoriamente difícil escribir código multiproceso seguro para subprocesos, de alto rendimiento y fácil de mantener que evite problemas como los interbloqueos y las condiciones de carrera. Realm busca simplificar esto para ti.

Tip

A partir del 10.26.0, Realm ofrece métodos de escritura asíncronos para realizar escrituras en segundo plano. Ver: Realizar una escritura en segundo plano. Con la escritura asíncrona, no es necesario pasar una referencia segura para subprocesos ni objetos congelados entre subprocesos.

Esta página describe cómo administrar manualmente los archivos y objetos de realm en todos los subprocesos. Realm también admite el uso de un actor Swift.Para gestionar el acceso al dominio mediante las funciones de concurrencia de Swift. Para obtener una descripción general de la compatibilidad con actores de Realm, consulte Usar Realm con actores - SDK de Swift.

Antes de explorar las herramientas de Realm para aplicaciones multiproceso, debes comprender y seguir estas tres reglas:

No bloquear para leer:
La arquitectura de Control de Concurrencia Multiversión (MVCC) de Realm elimina la necesidad de bloqueos en las operaciones de lectura. Los valores leídos nunca se corromperán ni se modificarán parcialmente. Se puede leer libremente del mismo archivo de Realm en cualquier hilo sin necesidad de bloqueos ni mutex. Un bloqueo innecesario supondría un cuello de botella en el rendimiento, ya que cada hilo podría tener que esperar su turno antes de leer.
Evite escrituras sincrónicas en el hilo de UI si escribe en un hilo en segundo plano:
Puedes escribir en un archivo Realm desde cualquier hilo, pero solo puede haber un escritor a la vez. Por lo tanto, las transacciones de escritura síncrona se bloquean entre sí. Una escritura síncrona en el hilo de la interfaz de usuario puede provocar que tu aplicación parezca no responder mientras espera a que se complete una escritura en un hilo en segundo plano. Device Sync escribe en un hilo en segundo plano, por lo que debes evitar las escrituras síncronas en el hilo de la interfaz de usuario con reinos sincronizados.
No pase objetos activos, colecciones o reinos a otros subprocesos:
Los objetos activos, las colecciones y las instancias de realm están confinados a subprocesos: es decir, solo son válidos en el subproceso en el que se crearon. En la práctica, esto significa que no se pueden pasar instancias activas a otros subprocesos. Sin embargo, Realm ofrece varios mecanismos para compartir objetos entre subprocesos.

Nuevo en la versión 10.26.0.

Puede agregar, modificar o eliminar objetos en segundo plano utilizando writeAsync.

Con writeAsyncNo es necesario pasar una referencia segura para subprocesos ni objetos congelados entre subprocesos. En su lugar, se llama realm.writeAsync a. Se puede proporcionar un bloque de finalización para que el método se ejecute en el subproceso de origen después de que la escritura se complete o falle.

Cosas a tener en cuenta al realizar escrituras en segundo plano:

  • Las escrituras asincrónicas bloquean el cierre o invalidan el reino

  • Puede confirmar o cancelar transacciones explícitamente

let realm = try! Realm()
// Query for a specific person object on the main thread
let people = realm.objects(Person.self)
let thisPerson = people.where {
$0.name == "Dachary"
}.first
// Perform an async write to add dogs to that person's dog list.
// No need to pass a thread-safe reference or frozen object.
realm.writeAsync {
thisPerson?.dogs.append(objectsIn: [
Dog(value: ["name": "Ben", "age": 13]),
Dog(value: ["name": "Lita", "age": 9]),
Dog(value: ["name": "Maui", "age": 1])
])
} onComplete: { _ in
// Confirm the three dogs were successfully added to the person's dogs list
XCTAssertEqual(thisPerson!.dogs.count, 3)
// Query for one of the dogs we added and see that it is present
let dogs = realm.objects(Dog.self)
let benDogs = dogs.where {
$0.name == "Ben"
}
XCTAssertEqual(benDogs.count, 1)
}

El SDK proporciona un Bool para indicar si el dominio está realizando una escritura asincrónica. La variable isPerformingAsynchronousWriteOperations se convierte en true tras una llamada a una de las siguientes opciones:

  • writeAsync

  • beginAsyncWrite

  • commitAsyncWrite

Esto se mantiene hasta que se completen todas las operaciones de escritura asíncrona programadas. Si bien esto es cierto, impide el cierre o la invalidación del dominio.

Para completar una escritura asincrónica, usted o el SDK deben llamar a:

Al usar el writeAsync método, el SDK gestiona la confirmación o cancelación de la transacción. Esto ofrece la comodidad de la escritura asíncrona sin necesidad de mantener manualmente el estado vinculado al ámbito del objeto. Sin embargo, en el writeAsync bloque, se puede llamar explícitamente commitAsyncWrite a cancelAsyncWrite o. Si se regresa sin llamar a ninguno de estos métodos,: writeAsync

  • Confirma la escritura después de ejecutar las instrucciones en el bloque de escritura.

  • Devuelve un error

En cualquier caso, esto completa la operación writeAsync.

Para tener más control sobre cuándo confirmar o cancelar la transacción de escritura asíncrona, use el método beginAsyncWrite. Al usar este método, debe confirmar explícitamente las transacciones. Si regresa sin confirmar una escritura asíncrona, la transacción se cancela. beginAsyncWrite devuelve un ID que puede pasar a cancelAsyncWrite.

commitAsyncWrite Confirma asincrónicamente una transacción de escritura. Este paso persiste los datos en el dominio. commitAsyncWrite puede tomar un bloque onComplete. Este bloque se ejecuta en el hilo de origen una vez que la confirmación se completa o falla con un error.

Llamar a commitAsyncWrite retorna inmediatamente. Esto permite que quien llama continúe mientras el SDK realiza la E/S en un subproceso en segundo plano. Este método devuelve un ID que se puede pasar a cancelAsyncWrite. Esto cancela la invocación pendiente del bloque de finalización. No cancela la confirmación en sí.

Puede agrupar llamadas secuenciales en commitAsyncWrite. Agrupar estas llamadas mejora el rendimiento de escritura, especialmente cuando las transacciones en lotes son pequeñas. Para permitir la agrupación de transacciones, configure el parámetro isGroupingAllowed en true.

Puedes llamar a cancelAsyncWrite en beginAsyncWrite o commitAsyncWrite. Al llamarlo en beginAsyncWrite, se cancela toda la transacción de escritura. Al llamarlo en commitAsyncWrite, solo se cancela un bloque onComplete que hayas pasado a commitAsyncWrite. No se cancela la confirmación en sí. Necesitas el ID del beginAsyncWrite o del commitAsyncWrite que quieres cancelar.

Para acceder al mismo archivo de dominio desde diferentes subprocesos, debe crear una instancia de dominio en cada subproceso que necesite acceso. Siempre que especifique la misma configuración, todas las instancias de dominio se asignarán al mismo archivo en el disco.

Una de las reglas clave al trabajar con Realm en un entorno multihilo es que los objetos están confinadosa cada hilo: no se puede acceder a las instancias de un reino, colección u objeto originadas en otros hilos. La arquitectura de Control de Concurrencia Multiversión (MVCC) de Realm implica que podría haber varias versiones activas de un objeto en cualquier momento. El confinamiento de hilos garantiza que todas las instancias de ese hilo tengan la misma versión interna.

Cuando necesita comunicarse a través de subprocesos, tiene varias opciones según su caso de uso:

  • Para modificar un objeto en dos subprocesos, consulte el objeto en ambos subprocesos.

  • Para reaccionar a los cambios realizados en cualquier hilo, utilice las notificaciones de Realm.

  • Para ver los cambios que ocurrieron en otro hilo en la instancia de reino del hiloactual, actualice su instancia de reino.

  • Para enviar una vista rápida y de solo lectura del objeto a otros subprocesos, "congele" el objeto.

  • Para conservar y compartir muchas vistas de solo lectura del objeto en su aplicación, copie el objeto desde el reino.

  • Para compartir una instancia de un dominio o un objeto específico con otro hilo o entre los límites de un actor, comparta una referencia segura para subprocesos a la instancia o al objeto del dominio. Para obtener más información, consulte "Pasar una ThreadSafeReference".

Al usar Realm en un subproceso en segundo plano, cree una cola serial. Realm no admite el uso de dominios en colas concurrentes, como la cola global().

// Initialize a serial queue, and
// perform realm operations on it
let serialQueue = DispatchQueue(label: "serial-queue")
serialQueue.async {
let realm = try! Realm(configuration: .defaultConfiguration, queue: serialQueue)
// Do something with Realm on the non-main thread
}

Las instancias Realm de,, Results Listy las instancias administradas de Objects están confinadas al subproceso. Esto significa que solo puede usarlas en el subproceso donde las creó. Sin embargo, Realm proporciona un mecanismo llamado referencias seguras para subprocesos que permite copiar una instancia creada en un subproceso a otro.

Novedades en la 10.20.0 versión: el contenedor @ThreadSafe y ThreadSafeReference cumplen con Sendable

Si está utilizando Swift 5.6 o superior, tanto el contenedor de propiedad @ThreadSafe como ThreadSafeReference se ajustan a Sendable.

Nuevo en la versión 10.17.0.

Puede pasar instancias confinadas a un subproceso a otro subproceso de la siguiente manera:

  1. Utilice la propiedad @ThreadSafe para declarar una variable que haga referencia al objeto original. Por definición, las variables con la propiedad @ThreadSafesiempre son opcionales.

  2. Pase la variable envuelta en @ThreadSafeal otro hilo.

  3. Utilice la variable con el atributo @ThreadSafecomo cualquier opción. Si el objeto referenciado se elimina del dominio, la variable de referencia se convierte en nula.

let realm = try! Realm()
let person = Person(name: "Jane")
try! realm.write {
realm.add(person)
}
// Create thread-safe reference to person
@ThreadSafe var personRef = person
// @ThreadSafe vars are always optional. If the referenced object is deleted,
// the @ThreadSafe var will be nullified.
print("Person's name: \(personRef?.name ?? "unknown")")
// Pass the reference to a background thread
DispatchQueue(label: "background", autoreleaseFrequency: .workItem).async {
let realm = try! Realm()
try! realm.write {
// Resolve within the transaction to ensure you get the
// latest changes from other threads. If the person
// object was deleted, personRef will be nil.
guard let person = personRef else {
return // person was deleted
}
person.name = "Jane Doe"
}
}

Otra forma de trabajar con un objeto en otro hilo es consultarlo de nuevo en ese hilo. Sin embargo, si el objeto no tiene una clave principal, consultarlo no es trivial. Se puede usar la @ThreadSafe envoltura en cualquier objeto, independientemente de si tiene una clave principal.

Ejemplo

El siguiente ejemplo muestra cómo usar @ThreadSafe en un parámetro de función. Esto es útil para funciones que se ejecutan de forma asíncrona o en otro subproceso.

Tip

Si su aplicación accede a Realm en un contexto async/await, marque el código con @MainActor para evitar fallas relacionadas con subprocesos.

func someLongCallToGetNewName() async -> String {
return "Janet"
}
@MainActor
func loadNameInBackground(@ThreadSafe person: Person?) async {
let newName = await someLongCallToGetNewName()
let realm = try! await Realm()
try! realm.write {
person?.name = newName
}
}
@MainActor
func createAndUpdatePerson() async {
let realm = try! await Realm()
let person = Person(name: "Jane")
try! realm.write {
realm.add(person)
}
await loadNameInBackground(person: person)
}
await createAndUpdatePerson()

Antes de la versión 10.17.0 del SDK de Realm Swift o en Objective-C, puedes pasar instancias confinadas a un subproceso a otro subproceso de la siguiente manera:

  1. Inicialice una ThreadSafeReference con el objeto confinado al hilo.

  2. Pase la referencia al otro hilo o cola.

  3. Resuelva la referencia en el dominio del otro subproceso llamando a Realm.resolve(_:). Utilice el objeto devuelto normalmente.

Importante

Debe resolver un ThreadSafeReference solo una vez. De lo contrario, el dominio de origen permanece anclado hasta que se desasigne la referencia. Por esta razón, ThreadSafeReference debería tener una duración corta.

let person = Person(name: "Jane")
let realm = try! Realm()
try! realm.write {
realm.add(person)
}
// Create thread-safe reference to person
let personRef = ThreadSafeReference(to: person)
// Pass the reference to a background thread
DispatchQueue(label: "background", autoreleaseFrequency: .workItem).async {
let realm = try! Realm()
try! realm.write {
// Resolve within the transaction to ensure you get the latest changes from other threads
guard let person = realm.resolve(personRef) else {
return // person was deleted
}
person.name = "Jane Doe"
}
}

Otra forma de trabajar con un objeto en otro hilo es consultarlo de nuevo en ese hilo. Sin embargo, si el objeto no tiene una clave principal, no es fácil consultarlo. Puedes usar ThreadSafeReference en cualquier objeto, independientemente de si tiene una clave principal. También puedes usarlo con listas y resultados.

La desventaja es que ThreadSafeReference requiere código repetitivo. Debe recordar encapsular todo en un DispatchQueue con un autoreleaseFrequency con el alcance adecuado para que los objetos no permanezcan en el subproceso en segundo plano. Por lo tanto, puede ser útil crear una extensión práctica para gestionar el código repetitivo de la siguiente manera:

extension Realm {
func writeAsync<T: ThreadConfined>(_ passedObject: T, errorHandler: @escaping ((_ error: Swift.Error) -> Void) = { _ in return }, block: @escaping ((Realm, T?) -> Void)) {
let objectReference = ThreadSafeReference(to: passedObject)
let configuration = self.configuration
DispatchQueue(label: "background", autoreleaseFrequency: .workItem).async {
do {
let realm = try Realm(configuration: configuration)
try realm.write {
// Resolve within the transaction to ensure you get the latest changes from other threads
let object = realm.resolve(objectReference)
block(realm, object)
}
} catch {
errorHandler(error)
}
}
}
}

Esta extensión añade un método writeAsync() a la clase Realm. Este método pasa automáticamente una instancia a un hilo en segundo plano.

Ejemplo

Supongamos que creaste una aplicación de correo electrónico y quieres eliminar todos los correos leídos en segundo plano. Puedes hacerlo con dos líneas de código. Ten en cuenta que el cierre se ejecuta en el hilo en segundo plano y recibe su propia versión del dominio y del objeto transferido:

let realm = try! Realm()
let readEmails = realm.objects(Email.self).where {
$0.read == true
}
realm.writeAsync(readEmails) { (realm, readEmails) in
guard let readEmails = readEmails else {
// Already deleted
return
}
realm.delete(readEmails)
}

No es posible compartir instancias de reino entre subprocesos.

Para usar el mismo archivo de Realm en varios subprocesos, abra una instancia de Realm diferente en cada subproceso. Siempre que use la misma configuración, todas las instancias de Realm se asignarán al mismo archivo en el disco.

Cuando se abre un realm, este refleja la confirmación exitosa de guardar más reciente y permanece en esa versión hasta que se actualiza. Esto significa que el realm no verá los cambios que se realizaron en otro hilo hasta la siguiente actualización. Un realm en el hilo de la interfaz de usuario — o, más precisamente, en cualquier hilo del bucle de eventos — se actualiza automáticamente al inicio de ese bucle. Sin embargo, debe actualizar manualmente las instancias Realm que no se encuentran en bucles de hilo o que tienen desactivada la actualización automática.

if (![realm autorefresh]) {
[realm refresh]
}
if (!realm.autorefresh) {
// Manually refresh
realm.refresh()
}

Los objetos activos y confinados en subprocesos funcionan correctamente en la mayoría de los casos. Sin embargo, algunas aplicaciones, como las basadas en arquitecturas reactivas basadas en flujos de eventos, necesitan enviar copias inmutables a varios subprocesos para su procesamiento antes de llegar al subproceso de la interfaz de usuario. Realizar una copia profunda cada vez sería costoso, y Realm no permite compartir instancias activas entre subprocesos. En este caso, se pueden congelar y descongelar objetos, colecciones y reinos.

La congelación crea una vista inmutable de un objeto, colección o reino específico. El objeto, colección o reino congelado sigue existiendo en el disco y no necesita copiarse completamente al pasarse a otros hilos. Puedes compartir libremente el objeto congelado entre hilos sin preocuparte por problemas. Al congelar un reino, sus objetos secundarios también se congelan.

Tip

Usar ThreadSafeReference con actores Swift

Realm no admite actualmente el uso de thaw() con actores Swift. Para trabajar con datos de Realm entre actores, utilice ThreadSafeReference en lugar de objetos congelados. Para obtener más información, consulte Pasar una ThreadSafeReference.

Los objetos congelados no están activos y no se actualizan automáticamente. Son, en realidad, instantáneas del estado del objeto en el momento de la congelación. Al descongelar un objeto, se devuelve una versión activa del objeto congelado.

// Get an immutable copy of the realm that can be passed across threads
RLMRealm *frozenRealm = [realm freeze];
RLMResults *dogs = [Dog allObjectsInRealm:realm];
// You can freeze collections
RLMResults *frozenDogs = [dogs freeze];
// You can still read from frozen realms
RLMResults *frozenDogs2 = [Dog allObjectsInRealm:frozenRealm];
Dog *dog = [dogs firstObject];
// You can freeze objects
Dog *frozenDog = [dog freeze];
// To modify frozen objects, you can thaw them
// You can thaw collections
RLMResults *thawedDogs = [dogs thaw];
// You can thaw objects
Dog *thawedDog = [dog thaw];
// You can thaw frozen realms
RLMRealm *thawedRealm = [realm thaw];
let realm = try! Realm()
// Get an immutable copy of the realm that can be passed across threads
let frozenRealm = realm.freeze()
assert(frozenRealm.isFrozen)
let people = realm.objects(Person.self)
// You can freeze collections
let frozenPeople = people.freeze()
assert(frozenPeople.isFrozen)
// You can still read from frozen realms
let frozenPeople2 = frozenRealm.objects(Person.self)
assert(frozenPeople2.isFrozen)
let person = people.first!
assert(!person.realm!.isFrozen)
// You can freeze objects
let frozenPerson = person.freeze()
assert(frozenPerson.isFrozen)
// Frozen objects have a reference to a frozen realm
assert(frozenPerson.realm!.isFrozen)

Al trabajar con objetos congelados, cualquier intento de realizar cualquiera de las siguientes acciones genera una excepción:

  • Abriendo una transacción de escritura en un reino congelado.

  • Modificar un objeto congelado.

  • Agregar un detector de cambios a un reino, una colección o un objeto congelado.

Puedes usar isFrozen para comprobar si el objeto está congelado. Esto siempre es seguro para subprocesos.

if ([realm isFrozen]) {
// ...
}
if (realm.isFrozen) {
// ...
}

Los objetos congelados siguen siendo válidos mientras el reino activo que los generó permanezca abierto. Por lo tanto, evite cerrar el reino activo hasta que todos los hilos hayan terminado con los objetos congelados. Puede cerrar un reino congelado antes de que se cierre el reino activo.

Importante

Sobre el almacenamiento en caché de objetos congelados

Almacenar en caché demasiados objetos congelados puede tener un impacto negativo en el tamaño del archivo Realm. "Demasiados" depende de tu dispositivo objetivo específico y el tamaño de tus objetos Realm. Si necesitas almacenar en caché un gran número de versiones, considera copiar lo que necesitas fuera de realm.

Para modificar un objeto congelado, debe descongelarlo. Como alternativa, puede consultarlo en un dominio no congelado y luego modificarlo. Llamar a thaw en un objeto, colección o dominio activo lo devuelve.

Descongelar un objeto o una colección también descongela el reino al que hace referencia.

// Read from a frozen realm
let frozenPeople = frozenRealm.objects(Person.self)
// The collection that we pull from the frozen realm is also frozen
assert(frozenPeople.isFrozen)
// Get an individual person from the collection
let frozenPerson = frozenPeople.first!
// To modify the person, you must first thaw it
// You can also thaw collections and realms
let thawedPerson = frozenPerson.thaw()
// Check to make sure this person is valid. An object is
// invalidated when it is deleted from its managing realm,
// or when its managing realm has invalidate() called on it.
assert(thawedPerson?.isInvalidated == false)
// Thawing the person also thaws the frozen realm it references
assert(thawedPerson!.realm!.isFrozen == false)
// Let's make the code easier to follow by naming the thawed realm
let thawedRealm = thawedPerson!.realm!
// Now, you can modify the todo
try! thawedRealm.write {
thawedPerson!.name = "John Michael Kane"
}

Al anexar a una colección congelada, se deben descongelar tanto la colección como el objeto que se desea anexar. En este ejemplo, consultamos dos objetos en un dominio congelado:

  • Un objeto Persona que tiene una propiedad Lista de objetos Perro

  • Un objeto de perro

Debemos descongelar ambos objetos antes de poder añadir el Perro a la colección Lista de Perros en la Persona. Si descongelamos solo el objeto Persona pero no el Perro, Realm genera un error.

La misma regla se aplica al pasar objetos congelados entre subprocesos. Un caso común podría ser llamar a una función en un subproceso en segundo plano para realizar algún trabajo en lugar de bloquear la interfaz de usuario.

// Get a copy of frozen objects.
// Here, we're getting them from a frozen realm,
// but you might also be passing them across threads.
let frozenTimmy = frozenRealm.objects(Person.self).where {
$0.name == "Timmy"
}.first!
let frozenLassie = frozenRealm.objects(Dog.self).where {
$0.name == "Lassie"
}.first!
// Confirm the objects are frozen.
assert(frozenTimmy.isFrozen == true)
assert(frozenLassie.isFrozen == true)
// Thaw the frozen objects. You must thaw both the object
// you want to append and the collection you want to append it to.
let thawedTimmy = frozenTimmy.thaw()
let thawedLassie = frozenLassie.thaw()
let realm = try! Realm()
try! realm.write {
thawedTimmy?.dogs.append(thawedLassie!)
}
XCTAssertEqual(thawedTimmy?.dogs.first?.name, "Lassie")

Realm proporciona acceso seguro, rápido, sin bloqueos y simultáneo entre subprocesos con su arquitectura de control de concurrencia multiversión (MVCC).

Si está familiarizado con un sistema de control de versiones distribuido como Git, es posible que ya tenga una comprensión intuitiva de MVCC. Dos elementos fundamentales de Git son:

  • Confirmaciones, que son escrituras atómicas.

  • Ramas, que son diferentes versiones del historial de confirmaciones.

De forma similar, Realm cuenta con escrituras confirmadas atómicamente en forma de transacciones. Realm también cuenta con múltiples versiones del historial en un momento dado, como las ramas.

A diferencia de Git, que promueve activamente la distribución y la divergencia mediante bifurcaciones, un realm solo tiene una versión más reciente en un momento dado y siempre escribe en la cabecera de esa última versión. Realm no puede escribir en una versión anterior. Esto significa que sus datos convergen en una versión más reciente de la verdad.

Un reino se implementa mediante una estructura de datos de árbol B+. El nodo de nivel superior representa una versión del reino; los nodos secundarios son objetos de esa versión. El reino tiene un puntero a su última versión, similar a cómo Git tiene un puntero a su confirmación HEAD.

Realm utiliza una técnica de copia en escritura para garantizar el aislamiento y la durabilidad. Al realizar cambios, Realm copia la parte relevante del árbol para su escritura. A continuación, Realm confirma los cambios en dos fases:

  • Realm escribe los cambios en el disco y verifica el éxito.

  • Luego, Realm establece su puntero de última versión para apuntar a la versión recién escrita.

Este proceso de confirmación en dos pasos garantiza que, incluso si la escritura falla a mitad de camino, la versión original no se corrompa, ya que los cambios se realizaron en una copia de la parte relevante del árbol. Asimismo, el puntero raíz del dominio apuntará a la versión original hasta que se garantice la validez de la nueva versión.

Ejemplo

El siguiente diagrama ilustra el proceso de confirmación:

Realm copia la parte relevante del árbol para las escrituras y luego reemplaza la última versión actualizando un puntero.
haga clic para ampliar
  1. El dominio está estructurado como un árbol. Tiene un puntero a su última versión, V1.

  2. Cuando se realiza una escritura, Realm crea una nueva versión V2 basada en V1. Realm crea copias de objetos para su modificación (A 1, C 1), mientras que los enlaces a objetos no modificados siguen apuntando a las versiones originales (B, D).

  3. Después de validar la confirmación, Realm actualiza el puntero a la nueva versión más reciente, V2. A continuación, Realm descarta los nodos antiguos que ya no están conectados al árbol.

Realm utiliza técnicas de copia cero, como el mapeo de memoria, para gestionar los datos. Al leer un valor del realm, prácticamente se ve el valor en el disco real, no una copia. Esta es la base de los objetos activos. Por eso también se puede configurar un puntero principal del realm para que apunte a la nueva versión tras validar la escritura en el disco.

  • Realm permite un código multiproceso simple y seguro cuando se siguen tres reglas:

    • No bloquees para leer

    • Evite escrituras en el hilo de UI si escribe en hilos en segundo plano o usa Sincronización de dispositivos

    • No pase objetos vivos a otros subprocesos.

  • Existe una forma adecuada de compartir objetos entre subprocesos para cada caso de uso.

  • Para ver los cambios realizados en otros subprocesos de su instancia de reino, debe actualizar manualmente las instancias de reino que no existen en subprocesos de "bucle" o que tienen la actualización automática deshabilitada.

  • Para las aplicaciones basadas en arquitecturas reactivas basadas en flujo de eventos, puede congelar objetos, colecciones y reinos para pasar copias superficiales de manera eficiente a diferentes subprocesos para su procesamiento.

  • La arquitectura de control de concurrencia multiversión (MVCC) de Realm es similar a la de Git. A diferencia de Git, Realm solo tiene una versión actualizada para cada reino.

  • Realm realiza compromisos en dos etapas para garantizar el aislamiento y la durabilidad.

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

Borrar