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
/ /
Realm Files

Bundle a Realm File - Swift SDK

Nota

Bundle Synchronized Realms

Swift SDK version 10.23.0 introduced the ability to bundle synchronized realms. Before version 10.23.0, you could only bundle local realms.

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.

Para crear y agrupar un archivo de reino con su aplicación:

  1. Crea un archivo de reino que contenga los datos que deseas agrupar.

  2. Agrupe el archivo de reino en su aplicación de producción.

  3. In your production application, open the realm from the bundled asset file. For synced realms, you must supply the partition key.

  1. Build a temporary realm app that shares the data model of your application.

  2. Open a realm and add the data you wish to bundle. If using a synchronized realm, allow time for the realm to fully sync.

  3. Use the writeCopy(configuration:) method to copy the realm to a new file:

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.
@MainActor
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: ) automatically compacts your realm to the smallest possible size before copying.

Nota

Diferencias entre los dominios sincronizados y los dominios solo locales

The above example uses a SyncConfiguration to configure a synchronized realm. To create a copy of a local realm, configure your realm with RealmConfiguration instead.

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:

  1. Create a new project with the exact same data models as your production app. Open a realm and add the data you wish to bundle. Since realm files are cross-platform, you can do this in a macOS app.

  2. Arrastre la copia compactada de su archivo de reino al Navegador de proyectos Xcode de su aplicación de producción.

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

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

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

If your app accesses Realm in an async/await context, mark the code with @MainActor to avoid threading-related crashes.

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.
@MainActor
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

The above example uses a SyncConfiguration to configure a synchronized realm. To create a copy of a local realm, configure your realm with Realm.Configuration instead.

Volver

Delete a Realm

En esta página