将主键添加到 RLMObject 需要迁移,有什么想法吗?

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

我正在开发一个 iOS 应用程序,其中 Realm.io 作为持久存储。 我刚刚通过添加主键更新了我的自定义 RLMObject 子类之一。

当我 运行 应用程序时,我收到一条错误消息,提示我需要添加迁移步骤:

'Migration is required for object type 'MY_REALM_OBJECT' due to the following errors:
- Property 'property_name' has been made a primary key.'

我有其他迁移代码,但在 Realm 文档中找不到任何关于如何将主键添加到 RLMObject 的内容。

有人知道怎么做吗?

您需要使用键 "primaryKeyProperty" 并将值设置为新对象迁移块中的 RLMObject 属性 名称。 primaryKeyProperty 是需要迁移的 RLMObjectSchema 属性 的名称。

[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";
          }];
     }
 }];

I have other migration code but can't find anything in the Realm docs on how to add a primary key to an RLMObject.

您已经将其设为主键! Realm 文档在 "Customizing Models" 部分对此进行了介绍。

由于 adding/modifying 模型的主键需要更新数据库文件(数据库中 table/column 的每个值都将被索引),因此您需要更新模式版本。

主键必须是唯一的。如果所有值都已经是唯一的,Realm 将自动为您应用迁移,因此您无需在迁移块中对 property_name 属性 进行任何更改。

如果 property_name 值并非全部都是唯一的,您需要使它们在迁移块中唯一。在 Realm 迁移块中更改数据的方式是迭代现有对象并使用键控下标在 newObject 上设置值:

[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++);
    }];
  }
}];

要了解有关迁移的更多信息,请阅读 Realm 文档的 "Migrations" 部分。

在 Swift 中,我使用以下代码成功将主键添加到我的领域:

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()
}

您需要确保使用主键的名称并使用 oldObject 属性设置它的值。每个主键都需要是唯一的。正如您在示例中看到的,此主键由三个值组成以使其唯一。