To make your iOS and tvOS apps fast and responsive, you must balance the computing time needed to lay out the visuals and handle user interactions with the time needed to process your data and run your business logic. Typically, app developers spread this work across multiple threads: the main or UI thread for all of the user interface-related work, and one or more background threads to compute heavier workloads before sending it to the UI thread for presentation. By offloading heavy work to background threads, the UI thread can remain highly responsive regardless of the size of the workload. But it can be notoriously difficult to write thread-safe, performant, and maintainable multithreaded code that avoids issues like deadlocking and race conditions. Realm aims to simplify this for you.
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.
Three Rules to Follow
Before exploring Realm's tools for multithreaded apps, you need to understand and follow these three rules:
- No bloquees 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.
- Avoid synchronous writes on the UI thread if you write on a background thread:
- 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.
- Don't pass live objects, collections, or realms to other threads:
- Live objects, collections, and realm instances are thread-confined: that is, they are only valid on the thread on which they were created. Practically speaking, this means you cannot pass live instances to other threads. However, Realm offers several mechanisms for sharing objects across threads.
Realizar una guardar en segundo plano
Novedad en la versión 10.26.0.
You can add, modify, or delete objects in the background using 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.
Things to consider when performing background writes:
Async writes block closing or invalidating the realm
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) }
Espere a que se completen las escrituras asincrónicas
El SDK proporciona un Bool para señalar si el realm está realizando una escritura asincrónica actualmente. La variable isPerformingAsynchronousWriteOperations se vuelve true tras llamar a uno de:
writeAsyncbeginAsyncWritecommitAsyncWrite
It remains true until all scheduled async write operations have completed. While this is true, this blocks closing or invalidating the realm.
Confirmar o cancelar una escritura asíncrona
To complete an async write, you or the SDK must call either:
Cuando usas el método writeAsync, el SDK gestiona la confirmación o cancelación de la transacción. Esto proporciona la comodidad de la escritura asíncrona sin la necesidad de mantener manualmente el estado vinculado al ámbito del objeto. Sin embargo, mientras estés en el bloque writeAsync, puedes llamar explícitamente a commitAsyncWrite o cancelAsyncWrite. Si regresas sin llamar a uno de estos métodos, writeAsync ya sea:
Commits the write after executing the instructions in the write block
Returns an error
In either case, this completes the writeAsync operation.
For more control over when to commit or cancel the async write transaction, use the beginAsyncWrite method. When you use this method, you must explicitly commit the transactions. Returning without committing an async write cancels the transaction. beginAsyncWrite returns an ID that you can pass to cancelAsyncWrite.
commitAsyncWrite confirma asíncronamente una transacción de escritura. Este es el paso que persiste los datos en el realm. commitAsyncWrite puede aceptar un bloque onComplete. . Este bloque se ejecuta en el hilo de origen una vez que se completa la confirmación o falla con un error.
Calling commitAsyncWrite immediately returns. This allows the caller to proceed while the SDK performs the I/O on a background thread. This method returns an ID that you can pass to cancelAsyncWrite. This cancels the pending invocation of the completion block. It does not cancel the commit itself.
You can group sequential calls to commitAsyncWrite. Batching these calls improves write performance; particularly when the batched transactions are small. To permit grouping transactions, set the isGroupingAllowed parameter to true.
You can call cancelAsyncWrite on either beginAsyncWrite or commitAsyncWrite. When you call it on beginAsyncWrite, this cancels the entire write transaction. When you call it on commitAsyncWrite, this cancels only an onComplete block you may have passed to commitAsyncWrite. It does not cancel the commit itself. You need the ID of the beginAsyncWrite or the commitAsyncWrite you want to cancel.
Communication Across Threads
Para acceder al mismo archivo Realm desde diferentes hilos, se debe instanciar una instancia Realm en cada hilo que requiera acceso. Siempre que especifiques la misma configuración, todas las instancias realm 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 confinados a un hilo: no puedes acceder a las instancias de un realm, colección u objeto que se originaron en otros hilos. La arquitectura de Control de concurrencia multiversión (MVCC) de Realm significa que podría haber muchas versiones activas de un objeto en cualquier momento. El confinamiento por hilo asegura que todas las instancias en ese hilo sean de la misma versión interna.
When you need to communicate across threads, you have several options depending on your use case:
To modify an object on two threads, query for the object on both threads.
To react to changes made on any thread, use Realm's notifications.
To see changes that happened on another thread in the current thread's realm instance, refresh your realm instance.
Para enviar una vista rápida y de solo lectura del objeto a otros subprocesos, "congele" el objeto.
To keep and share many read-only views of the object in your app, copy the object from the realm.
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".
Create a Serial Queue to use Realm on a Background Thread
When using Realm on a background thread, create a serial queue. Realm does not support using realms in concurrent queues, such as the global() queue.
// 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 }
Pasar instancias a través de subprocesos
Instances of Realm, Results, List, and managed Objects are thread-confined. That means you may only use them on the thread where you created them. However, Realm provides a mechanism called thread-safe references that allows you to copy an instance created on one thread to another thread.
Conformidad Sendable
New in version 10.20.0: @ThreadSafe wrapper and ThreadSafeReference conform to Sendable
Si está utilizando Swift 5.6 o superior, tanto el contenedor de propiedad @ThreadSafe como ThreadSafeReference se ajustan a Sendable.
Use the @ThreadSafe Wrapper
New in version 10.17.0.
Puedes pasar instancias confinadas por hilos a otro hilo de la siguiente manera:
Use the
@ThreadSafeproperty wrapper to declare a variable that references the original object. By definition,@ThreadSafe-wrapped variables are always optional.Pase la variable envuelta en
@ThreadSafeal otro hilo.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 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" } }
Another way to work with an object on another thread is to query for it again on that thread. But if the object does not have a primary key, it is not trivial to query for it. You can use the @ThreadSafe wrapper on any object, regardless of whether it has a primary key.
Ejemplo
The following example shows how to use @ThreadSafe on a function parameter. This is useful for functions that may run asynchronously or on another thread.
Tip
If your app accesses Realm in an async/await context, mark the code with @MainActor to avoid threading-related crashes.
func someLongCallToGetNewName() async -> String { return "Janet" } func loadNameInBackground( person: Person?) async { let newName = await someLongCallToGetNewName() let realm = try! await Realm() try! realm.write { person?.name = newName } } 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()
Usar ThreadSafeReference (Swift heredado/Objective-C)
Antes de la versión 10.17.0 de Realm Swift SDK o en Objective-C, puedes pasar instancias confinadas a un subproceso a otro subproceso de la siguiente manera:
Initialize a ThreadSafeReference with the thread-confined object.
Pasa la referencia al otro hilo o cola.
Resolve the reference on the other thread's realm by calling Realm.resolve(_:). Use the returned object as normal.
Importante
You must resolve a ThreadSafeReference exactly once. Otherwise, the source realm remains pinned until the reference gets deallocated. For this reason, ThreadSafeReference should be short-lived.
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" } }
Another way to work with an object on another thread is to query for it again on that thread. But if the object does not have a primary key, it is not trivial to query for it. You can use ThreadSafeReference on any object, regardless of whether it has a primary key. You can also use it with lists and results.
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
Suppose you made an email app and want to delete all read emails in the background. You can now do it with two lines of code. Note that the closure runs on the background thread and receives its own version of both the realm and passed object:
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) }
Use the Same Realm Across Threads
You cannot share realm instances across threads.
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.
Refreshing Realms
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() }
Frozen Objects
Live, thread-confined objects work fine in most cases. However, some apps -- those based on reactive, event stream-based architectures, for example -- need to send immutable copies around to many threads for processing before ultimately ending up on the UI thread. Making a deep copy every time would be expensive, and Realm does not allow live instances to be shared across threads. In this case, you can freeze and thaw objects, collections, and realms.
Freezing creates an immutable view of a specific object, collection, or realm. The frozen object, collection, or realm still exists on disk, and does not need to be deeply copied when passed around to other threads. You can freely share the frozen object across threads without concern for thread issues. When you freeze a realm, its child objects also become frozen.
Tip
Usa ThreadSafeReference con los actores de 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.
Frozen objects are not live and do not automatically update. They are effectively snapshots of the object state at the time of freezing. Thawing an object returns a live version of the frozen object.
// 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:
Opening a write transaction on a frozen realm.
Modifying a frozen object.
Adding a change listener to a frozen realm, collection, or object.
You can use isFrozen to check if the object is frozen. This is always thread-safe.
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.
Modify a Frozen Object
To modify a frozen object, you must thaw the object. Alternately, you can query for it on an unfrozen realm, then modify it. Calling thaw on a live object, collection, or realm returns itself.
Thawing an object or collection also thaws the realm it references.
// 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" }
Append to a Frozen Collection
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 List de objetos Dog
A Dog object
We must thaw both objects before we can append the Dog to the Dog List collection on the Person. If we thaw only the Person object but not the Dog, Realm throws an error.
The same rule applies when passing frozen objects across threads. A common case might be calling a function on a background thread to do some work instead of blocking the UI.
// 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's Threading Model in Depth
Realm proporciona acceso seguro, rápido, sin bloqueos y concurrente entre hilos con su Control de concurrencia multiversión (MVCC) arquitectura.
Compared and Contrasted with Git
If you are familiar with a distributed version control system like Git, you may already have an intuitive understanding of MVCC. Two fundamental elements of Git are:
Commits, which are atomic writes.
Branches, which are different versions of the commit history.
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.
Unlike Git, which actively supports distribution and divergence through forking, a realm only has one true latest version at any given time and always writes to the head of that latest version. Realm cannot write to a previous version. This means your data converges on one latest version of the truth.
Estructura interna
A realm is implemented using a B+ tree data structure. The top-level node represents a version of the realm; child nodes are objects in that version of the realm. The realm has a pointer to its latest version, much like how Git has a pointer to its HEAD commit.
Realm uses a copy-on-write technique to ensure isolation and durability. When you make changes, Realm copies the relevant part of the tree for writing. Realm then commits the changes in two phases:
Realm writes changes to disk and verifies success.
Realm then sets its latest version pointer to point to the newly-written version.
This two-step commit process guarantees that even if the write failed partway, the original version is not corrupted in any way because the changes were made to a copy of the relevant part of the tree. Likewise, the realm's root pointer will point to the original version until the new version is guaranteed to be valid.
Ejemplo
The following diagram illustrates the commit process:

The realm is structured as a tree. The realm has a pointer to its latest version, V1.
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).
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 datos. Cuando lees un valor del realm, en realidad estás viendo el valor en el disco físico, no una copia de él. Esta es la base de objetos activos. Esta es también la razón por la que un puntero principal de realm puede configurarse para apuntar a la nueva versión después de que la escritura en disco haya sido validada.
Resumen
Realm permite un código multiproceso simple y seguro cuando se siguen tres reglas:
don't lock to read
avoid writes on the UI thread if you write on background threads or use Device Sync
don't pass live objects to other threads.
There is a proper way to share objects across threads for each use case.
In order to see changes made on other threads in your realm instance, you must manually refresh realm instances that do not exist on "loop" threads or that have auto-refresh disabled.
For apps based on reactive, event-stream-based architectures, you can freeze objects, collections, and realms in order to pass shallow copies around efficiently to different threads for processing.
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.
Tipos enviables, no enviables y confinados a subprocesos
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 |