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
/ /
Datos del modelo

Change an Object Model - Swift SDK

Nota

Modificar las propiedades del esquema de un dominio sincronizado

The following page demonstrates how to modify schema properties of a local realm. Learn how to modify schema properties of a synced realm.

Cuando actualices tu esquema de objeto, debes incrementar la versión del esquema y ejecutar una migración.

Tip

This page provides general Swift and Objective-C migration examples. If you are using Realm with SwiftUI, see the SwiftUI-specific migration examples.

Si tu actualización de esquema añade propiedades opcionales o remueve propiedades, Realm puede realizar la migración automáticamente. Solo necesitas incrementar el schemaVersion.

For more complex schema updates, you must also manually specify the migration logic in a migrationBlock. This might include changes such as:

  • Agregar propiedades obligatorias que deben completarse con valores predeterminados

  • Combining fields

  • Renombrar un campo

  • Cambiar el tipo de un campo

  • Conversión de un objeto a un objeto incrustado

Tip

Bypass Migration During Development

Al desarrollar o depurar tu aplicación, puede preferirse borrar el realm en lugar de migrarlo. Utiliza la bandera deleteRealmIfMigrationNeeded para borrar la base de datos automáticamente cuando un desajuste de esquema requiera una migración.

Nunca publique una aplicación en producción con esta marca configurada en true.

A schema version identifies the state of a Realm Schema at some point in time. Realm tracks the schema version of each realm and uses it to map the objects in each realm to the correct schema.

Schema versions are integers that you may include in the realm configuration when you open a realm. If a client application does not specify a version number when it opens a realm then the realm defaults to version 0.

Importante

Increment Versions Monotonically

Migrations must update a realm to a higher schema version. Realm will throw an error if a client application opens a realm with a schema version that is lower than the realm's current version or if the specified schema version is the same as the realm's current version but includes different object schemas.

A local migration is a migration for a realm that does not automatically Sync with another realm. Local migrations have access to the existing Realm Schema, version, and objects and define logic that incrementally updates the realm to its new schema version. To perform a local migration you must specify a new schema version that is higher than the current version and provide a migration function when you open the out-of-date realm.

En iOS, puedes actualizar los datos subyacentes para reflejar los cambios en el esquema usando migraciones manuales. Durante una migración manual, puedes definir nuevas propiedades y propiedades eliminadas cuando se añaden o eliminan del esquema.

Realm puede migrar automáticamente las propiedades agregadas, pero debe especificar una versión de esquema actualizada cuando realice estos cambios.

Nota

Realm no establece automáticamente los valores de las nuevas propiedades obligatorias. Debe usar un bloque de migración para establecer los valores predeterminados de las nuevas propiedades obligatorias. Para las nuevas propiedades opcionales, los registros existentes pueden tener valores nulos. Esto significa que no necesita un bloque de migración al agregar propiedades opcionales.

Ejemplo

A realm using schema version 1 has a Person object type that has first name, last name, and age properties:

// In the first version of the app, the Person model
// has separate fields for first and last names,
// and an age property.
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"firstName", @"lastName", @"age"];
}
@end
// In the first version of the app, the Person model
// has separate fields for first and last names,
// and an age property.
class Person: Object {
@Persisted var firstName = ""
@Persisted var lastName = ""
@Persisted var age = 0
}

The developer decides that the Person class needs an email field and updates the schema.

// In a new version, you add a property
// on the Person model.
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
// Add a new "email" property.
@property NSString *email;
// New properties can be migrated
// automatically, but must update the schema version.
@property int age;
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"firstName", @"lastName", @"email", @"age"];
}
@end
// In a new version, you add a property
// on the Person model.
class Person: Object {
@Persisted var firstName = ""
@Persisted var lastName = ""
// Add a new "email" property.
@Persisted var email: String?
// New properties can be migrated
// automatically, but must update the schema version.
@Persisted var age = 0
}

Realm migra automáticamente el realm para ajustarse al esquema de Person actualizado. Pero el desarrollador debe definir la versión del esquema del realm como 2.

// When you open the realm, specify that the schema
// is now using a newer version.
RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
// Set the new schema version
config.schemaVersion = 2;
// Use this configuration when opening realms
[RLMRealmConfiguration setDefaultConfiguration:config];
RLMRealm *realm = [RLMRealm defaultRealm];
// When you open the realm, specify that the schema
// is now using a newer version.
let config = Realm.Configuration(
schemaVersion: 2)
// Use this configuration when opening realms
Realm.Configuration.defaultConfiguration = config
let realm = try! Realm()

Para borrar una propiedad de un esquema, remuévela de la clase del objeto y configura un schemaVersion del objeto de configuración del Realm. Borrar una propiedad no afectará a los objetos existentes.

Ejemplo

A realm using schema version 1 has a Person object type that has first name, last name, and age properties:

// In the first version of the app, the Person model
// has separate fields for first and last names,
// and an age property.
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"firstName", @"lastName", @"age"];
}
@end
// In the first version of the app, the Person model
// has separate fields for first and last names,
// and an age property.
class Person: Object {
@Persisted var firstName = ""
@Persisted var lastName = ""
@Persisted var age = 0
}

El desarrollador decide que el Person no necesita el campo age y actualiza el esquema.

// In a new version, you remove a property
// on the Person model.
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
// Remove the "age" property.
// @property int age;
// Removed properties can be migrated
// automatically, but must update the schema version.
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"firstName", @"lastName"];
}
@end
// In a new version, you remove a property
// on the Person model.
class Person: Object {
@Persisted var firstName = ""
@Persisted var lastName = ""
// Remove the "age" property.
// @Persisted var age = 0
// Removed properties can be migrated
// automatically, but must update the schema version.
}

Realm migra automáticamente el realm para ajustarse al esquema de Person actualizado. Pero el desarrollador debe definir la versión del esquema del realm como 2.

// When you open the realm, specify that the schema
// is now using a newer version.
RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
// Set the new schema version
config.schemaVersion = 2;
// Use this configuration when opening realms
[RLMRealmConfiguration setDefaultConfiguration:config];
RLMRealm *realm = [RLMRealm defaultRealm];
// When you open the realm, specify that the schema
// is now using a newer version.
let config = Realm.Configuration(
schemaVersion: 2)
// Use this configuration when opening realms
Realm.Configuration.defaultConfiguration = config
let realm = try! Realm()

Tip

Los desarrolladores de SwiftUI pueden ver un error que indica que se requiere una migración al agregar o eliminar propiedades. Esto está relacionado con el ciclo de vida de SwiftUI. Las vistas se diseñan y luego el modificador .environment establece la configuración.

Para resolver un error de migración en estas circunstancias, pase Realm.Configuration(schemaVersion: <Your Incremented Version>) al constructor ObservedResults.

For more complex schema updates, Realm requires a manual migration for old instances of a given object to the new schema.

Para cambiar el nombre de una propiedad durante una migración, utilice el método Migration.renameProperty(onType:from:to:).

Realm applies any new nullability or indexing settings during the rename operation.

Ejemplo

Cambie age el nombre de a yearsSinceBirth dentro de un bloque de migración.

RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
config.schemaVersion = 2;
config.migrationBlock = ^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion < 2) {
// Rename the "age" property to "yearsSinceBirth".
// The renaming operation should be done outside of calls to `enumerateObjects(ofType: _:)`.
[migration renamePropertyForClass:[Person className] oldName:@"age" newName:@"yearsSinceBirth"];
}
};
let config = Realm.Configuration(
schemaVersion: 2,
migrationBlock: { migration, oldSchemaVersion in
if oldSchemaVersion < 2 {
// Rename the "age" property to "yearsSinceBirth".
// The renaming operation should be done outside of calls to `enumerateObjects(ofType: _:)`.
migration.renameProperty(onType: Person.className(), from: "age", to: "yearsSinceBirth")
}
})

Tip

Puedes usar el método deleteRealmIfMigrationNeeded para eliminar el dominio si requiere una migración. Esto puede ser útil durante el desarrollo cuando necesitas iterar rápidamente y no quieres realizar la migración.

Para definir una lógica de migración personalizada,configure la propiedad migrationBlock de la Configuración al abrir un reino.

The migration block receives a Migration object that you can use to perform the migration. You can use the Migration object's enumerateObjects(ofType:_:) method to iterate over and update all instances of a given Realm type in the realm.

Ejemplo

A realm using schema version 1 has a Person object type that has separate fields for first and last names:

// In the first version of the app, the Person model
// has separate fields for first and last names,
// and an age property.
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"firstName", @"lastName", @"age"];
}
@end
// In the first version of the app, the Person model
// has separate fields for first and last names,
// and an age property.
class Person: Object {
@Persisted var firstName = ""
@Persisted var lastName = ""
@Persisted var age = 0
}

The developer decides that the Person class should use a combined fullName field instead of the separate firstName and lastName fields and updates the schema.

To migrate the realm to conform to the updated Person schema, the developer sets the realm's schema version to 2 and defines a migration function to set the value of fullName based on the existing firstName and lastName properties.

// In version 2, the Person model has one
// combined field for the full name and age as a Int.
// A manual migration will be required to convert from
// version 1 to this version.
@interface Person : RLMObject
@property NSString *fullName;
@property int age;
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"fullName", @"age"];
}
@end
RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
// Set the new schema version
config.schemaVersion = 2;
config.migrationBlock = ^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion < 2) {
// Iterate over every 'Person' object stored in the Realm file to
// apply the migration
[migration enumerateObjects:[Person className]
block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
// Combine name fields into a single field
newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
oldObject[@"firstName"],
oldObject[@"lastName"]];
}];
}
};
// Tell Realm to use this new configuration object for the default Realm
[RLMRealmConfiguration setDefaultConfiguration:config];
// Now that we've told Realm how to handle the schema change, opening the realm
// will automatically perform the migration
RLMRealm *realm = [RLMRealm defaultRealm];
// In version 2, the Person model has one
// combined field for the full name and age as a Int.
// A manual migration will be required to convert from
// version 1 to this version.
class Person: Object {
@Persisted var fullName = ""
@Persisted var age = 0
}
// In application(_:didFinishLaunchingWithOptions:)
let config = Realm.Configuration(
schemaVersion: 2, // Set the new schema version.
migrationBlock: { migration, oldSchemaVersion in
if oldSchemaVersion < 2 {
// The enumerateObjects(ofType:_:) method iterates over
// every Person object stored in the Realm file to apply the migration
migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
// combine name fields into a single field
let firstName = oldObject!["firstName"] as? String
let lastName = oldObject!["lastName"] as? String
newObject!["fullName"] = "\(firstName!) \(lastName!)"
}
}
}
)
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let realm = try! Realm()

Later, the developer decides that the age field should be of type String rather than Int and updates the schema.

To migrate the realm to conform to the updated Person schema, the developer sets the realm's schema version to 3 and adds a conditional to the migration function so that the function defines how to migrate from any previous version to the new one.

// In version 3, the Person model has one
// combined field for the full name and age as a String.
// A manual migration will be required to convert from
// version 2 to this version.
@interface Person : RLMObject
@property NSString *fullName;
@property NSString *age;
@end
@implementation Person
+ (NSArray<NSString *> *)requiredProperties {
return @[@"fullName", @"age"];
}
@end
RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
// Set the new schema version
config.schemaVersion = 3;
config.migrationBlock = ^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion < 2) {
// Previous Migration.
[migration enumerateObjects:[Person className]
block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
oldObject[@"firstName"],
oldObject[@"lastName"]];
}];
}
if (oldSchemaVersion < 3) {
// New Migration
[migration enumerateObjects:[Person className]
block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
// Make age a String instead of an Int
newObject[@"age"] = [oldObject[@"age"] stringValue];
}];
}
};
// Tell Realm to use this new configuration object for the default Realm
[RLMRealmConfiguration setDefaultConfiguration:config];
// Now that we've told Realm how to handle the schema change, opening the realm
// will automatically perform the migration
RLMRealm *realm = [RLMRealm defaultRealm];
// In version 3, the Person model has one
// combined field for the full name and age as a String.
// A manual migration will be required to convert from
// version 2 to this version.
class Person: Object {
@Persisted var fullName = ""
@Persisted var age = "0"
}
// In application(_:didFinishLaunchingWithOptions:)
let config = Realm.Configuration(
schemaVersion: 3, // Set the new schema version.
migrationBlock: { migration, oldSchemaVersion in
if oldSchemaVersion < 2 {
// Previous Migration.
migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
let firstName = oldObject!["firstName"] as? String
let lastName = oldObject!["lastName"] as? String
newObject!["fullName"] = "\(firstName!) \(lastName!)"
}
}
if oldSchemaVersion < 3 {
// New Migration.
migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
// Make age a String instead of an Int
newObject!["age"] = "\(oldObject!["age"] ?? 0)"
}
}
}
)
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let realm = try! Realm()

Tip

Linear Migrations

Avoid nesting or otherwise skipping if (oldSchemaVersion < X) statements in migration blocks. This ensures that all updates can be applied in the correct order, no matter which schema version a client starts from. The goal is to define migration logic which can transform data from any outdated schema version to match the current schema.

Embedded objects cannot exist independently of a parent object. When changing an Object to an EmbeddedObject, the migration block must ensure that every embedded object has exactly one backlink to a parent object. Having no backlinks or multiple backlinks raises the following exceptions:

At least one object does not have a backlink (data would get lost).
At least one object does have multiple backlinks.

Consulte los ejemplos de migración adicionales en el repositorio realm-swift.

Volver

Tipos admitidos

En esta página