问题
I'm working on an iOS app with Realm.io as the persistent store. I've just updated one of my custom RLMObject subclasses by adding a primary key.
When I run the app, I get an error telling me I need to add migration steps:
'Migration is required for object type 'MY_REALM_OBJECT' due to the following errors:
- Property 'property_name' has been made a primary key.'
I have other migration code but can't find anything in the Realm docs on how to add a primary key to an RLMObject.
Anyone know how to do this?
回答1:
You need to use the key "primaryKeyProperty" and set the value to the RLMObject property name in the migration block for the newObject.
primaryKeyProperty
is the name of the RLMObjectSchema property that needs to be migrated.
[RLMRealm setSchemaVersion:kLatestSchemaVersion
forRealmAtPath:theRealmPath
withMigrationBlock:^(RLMMigration *migration,
NSUInteger oldSchemaVersion)
{
if ( oldSchemaVersion < kLatestSchemaVersion )
{
[migration enumerateObjects:MyRealmClass.className
block:^(RLMObject *oldObject,
RLMObject *newObject)
{
newObject[@"primaryKeyProperty"] = @"propertyName";
}];
}
}];
回答2:
I have other migration code but can't find anything in the Realm docs on how to add a primary key to an RLMObject.
You've already made it a primary key! The Realm docs covers this in the "Customizing Models" section.
Since adding/modifying a primary key to your model requires the database file to be updated (every value for that table/column in the db will be indexed), you need to update the schema version.
Primary keys are required to be unique. If all the values are already unique, Realm will automatically apply the migration for you, so you don't need to make any changes to your property_name
property in the migration block.
If the property_name
values are not all already unique, you'll need to make them unique in a migration block. The way you change data in a Realm migration block is to iterate over the existing objects and set values on newObject
using keyed subscripting:
[RLMRealm setSchemaVersion:1
forRealmAtPath:realmPath
withMigrationBlock:^(RLMMigration *migration, NSUInteger oldSchemaVersion) {
if (oldSchemaVersion < 1) {
__block NSInteger incrementingPrimaryKeyValue = 0;
// The enumerateObjects:block: method iterates
// over every 'MY_REALM_OBJECT' object stored in the Realm file
[migration enumerateObjects:@"MY_REALM_OBJECT"
block:^(RLMObject *oldObject, RLMObject *newObject) {
// set the primary key to a unique value
newObject[@"property_name"] = @(incrementingPrimaryKeyValue++);
}];
}
}];
To learn more about migrations, please read the "Migrations" section of the Realm docs.
回答3:
In Swift, I successfully added a primary key to my Realm by using the following code:
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 1,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
var sharedUserID = ""
migration.enumerate(AdAccount.className()) { oldObject, newObject in
if oldSchemaVersion < 1 {
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
sharedUserID = oldObject!["userID"] as! String
newObject!["compoundKey"] = oldObject!["compoundkey"]
}
}
migration.enumerate(AdCampaign.className()) { oldObject, newObject in
if oldSchemaVersion < 1 {
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
let id = oldObject!["id"] as! String
let dateRange = oldObject!["daterange"]
let userID = sharedUserID
newObject!["dateRange"] = dateRange
newObject!["userID"] = userID
newObject!["compoundKey"] = "\(id)-\(dateRange)-\(userID)"
}
}
print("Migration complete.")
})
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
let realm = try! Realm()
}
You need to make sure to use the name of your primary key and set the value of it with oldObject properties. Each primary key needs to be unique. As you can see in the example, this primary key is made up of three values to make it unique.
来源:https://stackoverflow.com/questions/29261980/adding-a-primary-key-to-a-rlmobject-requires-migration-any-ideas-how