Adding a primary key to a RLMObject requires migration, any ideas how?

六眼飞鱼酱① 提交于 2020-01-01 12:42:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!