Nota
Paquete de reinos sincronizados
La versión 10.23.0 del SDK de Swift introdujo la posibilidad de agrupar dominios sincronizados. Antes de la versión 10.23.0, solo se podían agrupar dominios locales.
Realm permite agrupar archivos de realm. Al agrupar un archivo de realm, se incluye una base de datos y todos sus datos en la descarga de la aplicación.
Esto permite a los usuarios iniciar aplicaciones por primera vez con un conjunto de datos iniciales. En el caso de los dominios sincronizados, la agrupación puede evitar una larga descarga inicial la primera vez que un usuario abre la aplicación. En su lugar, los usuarios solo necesitan descargar los cambios sincronizados realizados desde que se generó el archivo agrupado.
Importante
Agrupación de reinos sincronizados
Si su aplicación backend utiliza Sincronización flexible: los usuarios podrían experimentar un reinicio del cliente la primera vez que abren el archivo de dominio incluido. Esto puede ocurrir cuando el tiempo máximo sin conexión del cliente está habilitado (esta opción está habilitada por defecto). Si el archivo de dominio incluido se generó más de los días especificados en la configuración de tiempo máximo sin conexión del cliente antes de que el usuario sincronice por primera vez, el cliente se reiniciará.
Las aplicaciones que reinician el cliente descargan el estado completo del dominio desde el backend de la aplicación. Esto anula las ventajas de agrupar un archivo de dominio. Para evitar reinicios del cliente y conservar las ventajas de agrupar archivos de dominio:
Evite utilizar un tiempo máximo sin conexión del cliente en aplicaciones que agrupan un reino sincronizado.
Si su aplicación utiliza un tiempo máximo de desconexión del cliente, asegúrese de que la descarga de la aplicación siempre incluya un archivo de dominio sincronizado recientemente. Genere un nuevo archivo con cada versión de la aplicación y asegúrese de que ninguna versión permanezca actualizada durante más días que el tiempo máximo de desconexión del cliente.
Overview
Para crear y agrupar un archivo de reino con su aplicación:
Crea un archivo de reino que contenga los datos que deseas agrupar.
Agrupe el archivo de reino en su aplicación de producción.
En su aplicación de producción, abra el dominio desde el archivo de recursos incluido. Para dominios sincronizados, debe proporcionar la clave de partición.
Crear un archivo de reino para agrupar
Cree una aplicación de reino temporal que comparta el modelo de datos de su aplicación.
Abra un dominio y agregue los datos que desea agrupar. Si usa un dominio sincronizado, espere a que se sincronice por completo.
Utilice el método writeCopy(configuration:) para copiar el reino a un nuevo archivo:
Tip
Si su aplicación accede a Realm en un async/await contexto, marque el código con @MainActor para evitar fallas relacionadas con subprocesos.
try await createBundledRealm() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func createBundledRealm() async throws { let app = App(id: YOUR_APP_SERVICES_APP_ID) // Log in the user whose realm you want to copy for bundling let seedUser = try await app.login(credentials: Credentials.anonymous) // Create a configuration to open the seed user's realm var config = seedUser.configuration(partitionValue: "Partition You Want to Bundle") config.objectTypes = [Todo.self] // Open the realm with the seed user's config let realm = try await Realm(configuration: config, downloadBeforeOpen: .always) print("Successfully opened realm: \(realm)") // Verify there is a todo object in the realm whose // owner's name is "Daenerys". When we open the bundled // realm later, we should see the same result. let todos = realm.objects(Todo.self) let daenerysTodos = todos.where { $0.owner == "Daenerys" } XCTAssertEqual(daenerysTodos.count, 1) // Specify an output directory for the bundled realm // We're using FileManager here for tested code examples, // but this could be a static directory on your computer. guard let outputDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } // Append a file name to complete the path let bundleRealmFilePath = outputDir.appendingPathComponent("seed.realm") // Update the config file path to the path where you want to save the bundled realm config.fileURL = bundleRealmFilePath // Check to see if there is already a realm at the bundled realm file path. If there // is already a realm there, delete it. if Realm.fileExists(for: config) { try Realm.deleteFiles(for: config) print("Successfully deleted existing realm at path: \(bundleRealmFilePath)") } else { print("No file currently exists at path") } // Write a copy of the realm at the URL we specified try realm.writeCopy(configuration: config) // Verify that we successfully made a copy of the realm XCTAssert(FileManager.default.fileExists(atPath: bundleRealmFilePath.path)) print("Successfully made a copy of the realm at path: \(bundleRealmFilePath)") // Verify that opening the realm at the new file URL works. // Don't download changes, because this can mask a copy // that does not contain the expected data. let copiedRealm = try await Realm(configuration: config, downloadBeforeOpen: .never) print("Successfully opened realm: \(realm)") // Verify that the copied realm contains the data we expect let copiedTodos = copiedRealm.objects(Todo.self) let daenerysCopiedTodos = copiedTodos.where { $0.owner == "Daenerys" } XCTAssertEqual(daenerysCopiedTodos.count, 1) print("Copied realm opens and contains this many tasks: \(daenerysCopiedTodos.count)") }
writeCopy(configuration: ) compacta automáticamente su reino al tamaño más pequeño posible antes de copiar.
Nota
Diferencias entre los dominios sincronizados y los dominios solo locales
El ejemplo anterior usa SyncConfiguration para configurar un dominio sincronizado. Para crear una copia de un dominio local, configure su dominio con RealmConfiguration.
Agrupar un archivo de reino en su aplicación de producción
Ahora que tiene una copia del dominio que contiene los datos iniciales, incorpórela a su aplicación de producción. En general, esto implica:
Crea un nuevo proyecto con los mismos modelos de datos que tu aplicación de producción. Abre un realm y añade los datos que quieres agrupar. Dado que los archivos realm son multiplataforma, puedes hacerlo en una aplicación macOS.
Arrastre la copia compactada de su archivo de reino al Navegador de proyectos Xcode de su aplicación de producción.
Vaya al objetivo de su aplicación Build Phases Pestaña en Xcode. Agregue el archivo realm a la fase de compilación Copy Bundle Resources.
En este punto, tu aplicación puede acceder al archivo de dominio incluido. Encuentra su ruta con Bundle.main.path(forResource:ofType).
Puedes abrir el Realme directamente en la ruta del paquete si la propiedad readOnly está configurada en true en la Configuración de Realm. Si deseas modificar el Realm incluido en el paquete, primero copia el archivo incluido en la carpeta Documentos de tu aplicación configurando seedFilePath con la URL del Realm incluido en tu configuración.
Tip
Consulta la aplicación de ejemplo de migración para una aplicación funcional completa que usa un realm local integrado.
Abrir un reino desde un archivo de reino incluido
Ahora que tiene una copia del dominio incluida en su aplicación de producción, necesita agregar código para usarla. Use el método seedFilePath al configurar su dominio para abrirlo desde el archivo incluido:
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.
try await openBundledSyncedRealm() // Opening a realm and accessing it must be done from the same thread. // Marking this function as `@MainActor` avoids threading-related issues. func openBundledSyncedRealm() async throws { let app = App(id: YOUR_APP_SERVICES_APP_ID) // Log in an app user who will use the bundled realm let user = try await app.login(credentials: Credentials.anonymous) // Create a configuration for the app user's realm // This should use the same partition value as the bundled realm var newUserConfig = user.configuration(partitionValue: "Partition You Want to Bundle") newUserConfig.objectTypes = [Todo.self] // Find the path of the seed.realm file in your project let realmURL = Bundle.main.url(forResource: "seed", withExtension: ".realm") print("The bundled realm URL is: \(realmURL)") // When you use the `seedFilePath` parameter, this copies the // realm at the specified path for use with the user's config newUserConfig.seedFilePath = realmURL // Open the synced realm, downloading any changes before opening it. // This starts with the existing data in the bundled realm, but checks // for any updates to the data before opening it in your application. let realm = try await Realm(configuration: newUserConfig, downloadBeforeOpen: .always) print("Successfully opened the bundled realm") // Read and write to the bundled realm as normal let todos = realm.objects(Todo.self) // There should be one todo whose owner is Daenerys because that's // what was in the bundled realm. var daenerysTodos = todos.where { $0.owner == "Daenerys" } XCTAssertEqual(daenerysTodos.count, 1) print("The bundled realm has \(daenerysTodos.count) todos whose owner is Daenerys") // Write as usual to the realm, and see the object count increment let todo = Todo(value: ["name": "Banish Ser Jorah", "owner": "Daenerys", "status": "In Progress"]) try realm.write { realm.add(todo) } print("Successfully added a todo to the realm") daenerysTodos = todos.where { $0.owner == "Daenerys" } XCTAssertEqual(daenerysTodos.count, 2) }
Nota
Diferencias entre los dominios sincronizados y los dominios solo locales
El ejemplo anterior usa SyncConfiguration para configurar un dominio sincronizado. Para crear una copia de un dominio local, configure su dominio con Realm.Configuration.