Ios RLMEException,对象类型需要迁移

Ios RLMEException,对象类型需要迁移,ios,swift,realm,Ios,Swift,Realm,我有一个对象NotSureItem,其中我有三个属性title,它们的名称是从我后来添加的text和textDescription重命名的,还有一个dateTime属性。现在,当我要运行我的应用程序时,当我想向这些属性添加内容时,它会崩溃。它显示以下语句 'Migration is required for object type 'NotSureItem' due to the following errors: - Property 'text' is missing from latest

我有一个对象
NotSureItem
,其中我有三个属性
title
,它们的名称是从我后来添加的
text
textDescription
重命名的,还有一个
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()
}

只要你没有发布你的应用,你就可以删除你的应用,然后再次运行

每次更改领域对象的属性时,现有数据库都与新数据库不兼容

只要您仍处于开发阶段,您就可以从模拟器/设备中删除应用程序,然后重新启动

稍后,当您的应用程序发布后您更改对象的属性时,您必须实现到新数据库版本的迁移

要实际执行迁移,需要实现领域迁移块。通常,您会将块添加到
应用程序(应用程序:didFinishLaunchingWithOptions:)

var-configuration=Realm.configuration(
阴谋厌恶:1,
migrationBlock:{migration,oldSchemaVersion in
如果oldschemaversation<1{
//如果只是更改了模型属性的名称,则可以执行此操作
migration.renameProperty(onType:NotSureItem.className(),从“文本”到“标题”)
//如果要用某些值填充新属性,则必须枚举
//选择现有对象并设置新值
enumerateObjects(类型:NotSureItem.className()){oldObject,中的newObject
将text=oldObject![“text”]设为!字符串
newObject![“textDescription”]=“标题为\(文本)”
}
//如果添加了新属性或删除了属性,则不需要
//必须做任何事情,因为领域自动检测到
}
}
)
Realm.Configuration.defaultConfiguration=配置
//现在打开领域文件可以确保执行迁移
让我试试!领域()

每当您的方案更改时,您必须增加迁移块中的
schemaversation
,并更新块中所需的迁移。

下面的代码对我有用

- (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;
}
-(BOOL)应用程序:(UIApplication*)应用程序使用选项完成启动:(NSDictionary*)启动选项
{  
RLMRealmConfiguration*config=[RLMRealmConfiguration defaultConfiguration];
config.schemaVersion=2;
config.migrationBlock=^(RLMMiglation*迁移,uint64\u t旧模式){
//enumerateObjects:block:方法迭代
//在域文件中存储的每个“Person”对象上
[迁移枚举对象:Person.className]
块:^(RLMObject*oldObject,RLMObject*newObject){
//仅将“fullName”属性添加到架构版本为0的领域
if(oldschemaversation<1){
newObject[@“fullName”]=[NSString stringWithFormat:@“%@%@”,
oldObject[@“firstName”],
oldObject[@“lastName”];
}
//将“email”属性添加到架构版本为0或1的领域
if(oldschemaversation<2){
新对象[@“电子邮件”]=@;
}
}];
};
[RLMRealmConfiguration setDefaultConfiguration:config];
//现在我们已经更新了模式版本并提供了迁移块,
//打开过时的领域将自动执行迁移和
//打开这个领域将会成功
[RLMRealm defaultRealm];
返回YES;
}

更多信息:

您修改的数据库与保存的数据库不再兼容,这就是需要迁移的原因。您可以选择删除旧的数据库文件并重新开始(如果您处于初始开发阶段,效果会很好),或者如果您处于活动状态,则执行迁移


您可以通过定义架构版本并在领域配置中提供数据库迁移“脚本”来实现这一点。整个过程都记录在这里(以及代码示例):

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

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

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

对于最小迁移任务,上面链接中的以下代码段可以自动执行迁移,并将与AppDelegate的
disFinishLaunchWithOptions
方法一起使用:

let config=Realm.Configuration(
//设置新架构版本。该版本必须大于以前使用的版本
//版本(如果以前从未设置过架构版本,则版本为0)。
阴谋厌恶:1,
//设置使用打开域时自动调用的块
//低于上面设置的架构版本
migrationBlock:{migration,oldSchemaVersion in
//我们还没有迁移任何内容,所以oldSchemaVersion==0
if(oldschemaversation<1){
//无事可做!
//领域将自动检测新属性和删除的属性
//并将自动更新磁盘上的架构
}
})
//告诉领域将此新配置对象用于默认领域
Realm.Configuration.defaultConfiguration=config
//现在我们已经告诉Realm如何处理模式更改,打开文件
//将自动执行迁移
让我们试试!Realm()
只需增加架构版本 领域将自动检测新属性和删除的属性
var config=Realm.Configuration(
//设置新架构版本。该版本必须大于以前使用的版本
//版本(如果以前从未设置过架构版本,则版本为0)。
阴谋厌恶:2,
[[NSFileManager defaultManager] removeItemAtURL:[RLMRealmConfiguration defaultConfiguration].fileURL error:nil];
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)
        }