RLMException,需要为对象类型进行迁移。

48

我有一个对象NotSureItem,其中有三个属性:title,它的名称从text改名而来,以及我后来添加的textDescriptiondateTime属性。现在当我运行我的应用程序并想要向这些属性中添加一些内容时,它会崩溃,并显示以下语句。

'Migration is required for object type 'NotSureItem' due to the following errors:
- Property 'text' is missing from latest object model.
- Property 'title' has been added to latest object model.
- Property 'textDescription' has been added to latest object model.'

这是我的代码:

import Foundation
import Realm

class NotSureItem: RLMObject {
    dynamic var title = ""   // renamed from 'text'
    dynamic var textDescription = "" // added afterwards
    dynamic var dateTime = NSDate()
}
8个回答

135
只要您还没有发布您的应用程序,您可以简单地删除您的应用程序并重新运行它。
每当您更改Realm对象上的属性时,您现有的数据库就会与新数据库不兼容。
只要您仍处于开发阶段,您可以从模拟器/设备中简单地删除该应用程序,然后再次启动它。
稍后,当您的应用程序已经发布,并且您在对象上更改了属性,您必须实现迁移以升级到新的数据库版本。
要执行迁移,您需要实现一个Realm迁移块。通常,您会将该块添加到application(application:didFinishLaunchingWithOptions:)中:
var configuration = Realm.Configuration(
    schemaVersion: 1,
    migrationBlock: { migration, oldSchemaVersion in
        if oldSchemaVersion < 1 {

            // if just the name of your model's property changed you can do this 
            migration.renameProperty(onType: NotSureItem.className(), from: "text", to: "title")

            // if you want to fill a new property with some values you have to enumerate
            // the existing objects and set the new value
            migration.enumerateObjects(ofType: NotSureItem.className()) { oldObject, newObject in
                let text = oldObject!["text"] as! String
                newObject!["textDescription"] = "The title is \(text)"
            }

            // if you added a new property or removed a property you don't
            // have to do anything because Realm automatically detects that
        }
    }
)
Realm.Configuration.defaultConfiguration = configuration

// opening the Realm file now makes sure that the migration is performed
let realm = try! Realm()

无论何时您的方案发生更改,都必须在迁移块中增加schemaVersion并更新块内所需的迁移。

2
这是正确的答案。只是有人给它投了反对票。如果这个答案对你有用,你能否接受它,这样它就会被标记为正确答案? - joern
我想再问您一件事情,我的数据已经成功保存在realm文件中,但是当我再次运行我的应用程序时,我的表视图中是空的。@joern - shahin ali agharia
你能否发布一个新的问题来描述这个情况?为了能够帮助你,我需要看到与此相关的代码部分(如何、在哪里以及何时检索数据)。在评论中进行讨论并不是很有效。 - joern
https://dev59.com/sJLea4cB1Zd3GeqPxQ2A - AJit
1
这个答案应该被删除,因为它是不正确的。你应该提供迁移指南,而不是解决问题的变通方法。 - Evgeniy Kleban
显示剩余9条评论

25
删除应用并重新安装不是一个好的做法。我们应该在开发过程中从第一次遇到迁移需求开始就加入一些迁移步骤。SilentDirge提供的链接很好:realm migration document,其中提供了处理不同情况的良好示例。
对于最小的迁移任务,上述链接中的以下代码片段可以自动执行迁移,并与AppDelegate的disFinishLaunchWithOptions方法一起使用:

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
    // We haven’t migrated anything yet, so oldSchemaVersion == 0
    if (oldSchemaVersion < 1) {
      // Nothing to do!
      // Realm will automatically detect new properties and removed properties
      // And will update the schema on disk automatically
    }
  })

// 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 _ = try! Realm()


我在Realm和ReactNative开发方面是一个完全的新手,现在遇到了这些问题。我想知道添加这段代码是否可以让Realm自动检测差异?还需要采取其他措施吗? - Isaac
@Isaac,每当您的Realm对象有新的或删除的字段时,您需要提高“schemaVersion”。 - CodeBrew
对我很有用。感谢@CodeBrew - Alejandro Gonzalez

11

以下代码适用于我

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{  
RLMRealmConfiguration *config = [RLMRealmConfiguration    defaultConfiguration];
 config.schemaVersion = 2;
config.migrationBlock = ^(RLMMigration *migration, uint64_t  oldSchemaVersion) {
  // The enumerateObjects:block: method iterates
  // over every 'Person' object stored in the Realm file
  [migration enumerateObjects:Person.className
                    block:^(RLMObject *oldObject, RLMObject *newObject) {
    // Add the 'fullName' property only to Realms with a schema version of 0
    if (oldSchemaVersion < 1) {
      newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
                            oldObject[@"firstName"],
                            oldObject[@"lastName"]];
    }

    // Add the 'email' property to Realms with a schema version of 0 or 1
    if (oldSchemaVersion < 2) {
     newObject[@"email"] = @"";
    }
  }];
 };
[RLMRealmConfiguration setDefaultConfiguration:config];

// now that we have updated the schema version and provided a migration block,
// opening an outdated Realm will automatically perform the migration and
// opening the Realm will succeed
[RLMRealm defaultRealm];

return YES;
}

更多信息:https://realm.io/docs/objc/latest/#getting-started


5

只需增加模式版本号

Realm会自动检测新属性和已删除的属性

var 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: 2,
            
            // 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
                // We haven’t migrated anything yet, so oldSchemaVersion == 0
                if (oldSchemaVersion < 1) {
                    // Nothing to do!
                    // Realm will automatically detect new properties and removed properties
                    // And will update the schema on disk automatically
                }
        })
        
               
        do{
            realm = try Realm(configuration: config)
            
            print("Database Path : \(config.fileURL!)")
        }catch{
            print(error.localizedDescription)
        }

3

您修改后的数据库与保存的数据库不兼容,因此需要进行迁移。您可以选择删除旧的数据库文件并重新开始(如果您处于初始开发阶段,则效果很好),或者如果您正在运行,请执行迁移。

您可以通过在Realm配置中定义模式版本并提供数据库迁移“脚本”来完成此操作。整个过程在此处记录(以及代码示例):这里


2
您可以通过以下方式在启动时清除数据库:
[[NSFileManager defaultManager] removeItemAtURL:[RLMRealmConfiguration defaultConfiguration].fileURL error:nil];

1
如果你在增加模式版本号后仍然遇到此错误,请进行双重检查。是否在更新App Delegate中的模式版本之前调用了任何Realm对象。

在我的情况下,在执行代码迁移语句之前,我尝试在App Delegate中访问一个Realm对象。

始终将迁移代码编写在App Delegate的第一行(DidfinishLaunchingWithOptions)上,以更安全的方式进行。


0

如果您对领域进行了“任何”更改,都会出现迁移错误。

要解决此问题:

  1. 关闭Xcode
  2. 在终端中运行以下代码: rm -rf ~/Library/Developer/Xcode/DerivedData/
  3. 重新打开Xcode并构建。
  4. 问题已解决 这将删除创建错误的Xcode数据。

每次更改与“Realm”有关的内容时,请执行此操作,您就可以恢复并运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接