在 Core Data 中进行重量级迁移时尝试迁移 nil 属性值

Posted

技术标签:

【中文标题】在 Core Data 中进行重量级迁移时尝试迁移 nil 属性值【英文标题】:Trying to migrate nil attribute value when doing heavy weight migration in Core Data 【发布时间】:2014-03-10 20:23:19 【问题描述】:

在我的 ios 应用程序中,我正在对实体进行重量级迁移,其中我将属性的类型从旧数据模型中的 Integer64 转换为新数据模型中的 String 类型。此属性的转换似乎工作正常。但是,我遇到的问题是同一个实体的另一个属性为空(它应该是),当这个属性被迁移到新模式中的同一个实体时,一个错误被标记:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "date"; desired type = NSDate; given type = NSNull; value = <null>.'

我不确定为什么要标记此错误,因为该属性在数据模型中被标记为可选。我想简单地将属性的 nil 值“按原样”迁移到新数据模型中的相同属性,而不进行任何更改或修改。

这是我正在使用的 NSEntityMigrationPolicy 子类的相关代码:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError *__autoreleasing *)error 

    NSManagedObject *newObject;
    NSEntityDescription *sourceInstanceEntity = [sInstance entity];

    //correct entity?  just to be sure
    if ([[sourceInstanceEntity name] isEqualToString:@"MyEntity"]) 
        newObject = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:[manager destinationContext]];

        //obtain the attributes
        NSDictionary *keyValDict = [sInstance committedValuesForKeys:nil];
        NSArray *allKeys = [[[sInstance entity] attributesByName] allKeys];
        //loop over the attributes
        for (NSString *key in allKeys) 
            //get key and value
            id value = [keyValDict objectForKey:key];
            if ([key isEqualToString:@"integerType"]) 
                //here retrieve old value
                NSNumber *oldValue = [keyValDict objectForKey:key];
                //here do conversion as needed
                NSString *stringType = [oldValue stringValue];
                //then store new value
                [newObject setValue:stringType forKey:key];
              else  //no need to modify the value, Copy it across -- this is where I believe the problem is
                [newObject setValue:value forKey:key];
            
        

        [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];
    

    return YES;

谁能看出我做错了什么?

【问题讨论】:

【参考方案1】:

问题是您在字典中返回了 NSNull 类,这意味着您试图将错误类型的类传递给新的 NSManagedObject 实例。

如果您阅读-committedValuesForKeys: 上的文档,您会看到:

nil 值由NSNull 的实例表示。

这是你的问题。

就我个人而言,我不会以这种方式处理价值观。相反,我会这样做:

NSDictionary *allAttributes = [[sInstance entity] attributesByName];

for (NString *key in allAttributes) 
  id value = [sInstance valueForKey:key];
  if ([key isEqualToString:@"integerType"]) 
    //here retrieve old value
    NSNumber *oldValue = [keyValDict objectForKey:key];
    //here do conversion as needed
    NSString *stringType = [oldValue stringValue];
    //then store new value
    [newObject setValue:stringType forKey:key];
    else  //no need to modify the value, Copy it across -- this is where I believe the problem is
    [newObject setValue:value forKey:key];
  

您直接从对象中获取值,您将得到正确的nil 返回。

【讨论】:

非常感谢您的解决方案,它奏效了!如果您有时间,可以看看下一个问题:***.com/questions/22330445/… 吗?再次感谢您的宝贵时间和帮助!

以上是关于在 Core Data 中进行重量级迁移时尝试迁移 nil 属性值的主要内容,如果未能解决你的问题,请参考以下文章

Core Data(iPhone)实现“自动轻量级迁移”

迁移大型 Core Data 数据库崩溃

Core Data 轻量级迁移后执行自定义代码

Core Data轻量级迁移有多少个迁移步骤?

Core Data 的推断映射模型创建(轻量级迁移)崩溃。线程问题?

使用 Core Data 轻量级迁移和 UIManagedDocument 的“找不到源存储模型”