【问题标题】:RLMException, Migration is required for object typeRLMException,对象类型需要迁移
【发布时间】:2016-01-26 14:24:59
【问题描述】:

我有一个对象NotSureItem,其中我有三个属性title,其名称从texttextDescription 重命名,我后来添加了一个dateTime 属性。现在,当我要运行我的应用程序时,当我想向这些属性添加一些东西时它会崩溃。它显示以下语句。

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

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    如果您在增加 schemaVersion 后仍收到此错误。然后进行仔细检查。是否在更新 App Delegate 中的架构版本之前调用任何 Realm 对象

    在我的例子中,我试图在执行代码迁移语句之前访问 App Delegate 中的领域对象。

    始终将迁移代码写在 App Delegate (DidfinishLaunchingWithOptions) 的第一行,这样更安全。

    【讨论】:

      【解决方案2】:

      只要您尚未发布您的应用,您只需删除您的应用并重新运行即可。

      每次更改 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 并在块内更新所需的迁移。

      【讨论】:

      • 这是正确的答案。只是有人否决了它。如果它对您有用,您能否接受答案,所以这被标记为正确答案?
      • 我想再问你一件事,我的数据已成功保存在领域文件中,但当我再次运行我的应用程序时,它在我的表格视图中为空。@joern
      • 您能为此发布一个新问题吗?为了能够在这方面为您提供帮助,我需要查看您的代码中相关的部分(检索数据的方式、地点和时间)。这在评论线程中并没有真正起作用。
      • 这个答案应该被删除,因为它不正确。您应该提供迁移指南,而不是这种问题的解决方法。
      【解决方案3】:

      只需增加架构版本

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

      【讨论】:

        【解决方案4】:

        删除应用并重新安装不是一个好习惯。从我们第一次遇到迁移需求开始,我们就应该在开发过程中加入一些迁移步骤。 SilentDirge 给出的链接很好:realm migration document,它为处理不同情况提供了很好的例子。

        对于最小迁移任务,上面链接中的以下代码 sn -p 可以自动执行迁移,并与 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 每次您的 Realm 对象有新的或删除的字段时,您都需要敲击schemaVersion
        【解决方案5】:

        您可以像这样在启动时擦除数据库:

        [[NSFileManager defaultManager] removeItemAtURL:[RLMRealmConfiguration defaultConfiguration].fileURL error:nil];
        

        【讨论】:

          【解决方案6】:

          您修改后的数据库不再与保存的数据库兼容,这就是需要迁移的原因。您的选择是删除旧的数据库文件并重新开始(如果您处于初始开发阶段,效果很好),或者如果您在现场,请进行迁移。

          您可以通过定义架构版本并在您的 Realm 配置中提供数据库迁移“脚本”来实现此目的。整个过程记录在这里(连同代码示例):here

          【讨论】:

            【解决方案7】:

            下面的代码对我有用

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-07-01
              • 1970-01-01
              相关资源
              最近更新 更多