我真的需要将我的项目货币转换为NSDecimalNumber吗?

时间:2015-10-02 03:34:11

标签: ios objective-c core-data currency core-data-migration

是的,我知道我应该使用NSDecimalNumber来处理货币,金钱,价格...... I've read this.问题是,我调整了一个现有项目,使用NSString和{ {1}}(NSNumberfloatdouble ...)作为货币。他们使用CGFloat处理浮点数,因为我可以看到它不是一个大问题(但是?)。这些货币存储在coredata中。

现在,如果我想将所有这些货币转换为NSNumberFormatter,我将不得不在代码中进行大规模重构并在coredata中进行迁移。问题出在这里:

  
      
  1. 如果(我假设)NSDecimalNumberdoubleCGFloat可以保存与NSNumber一样大的值,为什么要使用NSDecimalNumber因为我可以使用   其他NSDecimalNumber?是因为表现吗?

  2.   
  3. 如果需要转换,我当然可以在MappingModel的帮助下进行自动迁移,或者我是否有   修改自定义迁移政策?

  4.   

因为coredata同时使用NSNumberFormatterNSString作为货币,所以请帮我找到从两种数据类型迁移的解决方案。我不习惯在coredata中使用NSNumber。提前谢谢。

修改

好的,我知道NSDecimalNumber是必要的。请帮我回答第二个问题:我可以使用mappingModel + NSDecimalNumber之类的东西进行自动迁移(这是不正确的,因为decimalValue返回FUNCTION($source.price, "decimalValue"),而不是NSDecimal)。我真的必须编写自定义迁移策略吗?

3 个答案:

答案 0 :(得分:1)

  

我真的必须编写自定义迁移策略吗?

是。为需要转换的每个实体创建NSEntityMigrationPolicy的子类,并实现menthod createDestinationInstancesForSourceInstance:entityMapping:manager:error:。在映射模型中的实体的自定义策略中输入此类的名称。

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
    entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager
    error:(NSError **)error
{
    BOOL aBool = [super createDestinationInstancesForSourceInstance:sInstance entityMapping:mapping manager:manager error:error];
    if (aBool)
    {
        NSArray *aSourceArray = [[NSArray alloc] initWithObjects:&sInstance count:1];
        NSArray *aDestArray = [manager destinationInstancesForEntityMappingNamed:[mapping name] sourceInstances:aSourceArray];
        if (aDestArray && [aDestArray count] > 0)
        {
            NSManagedObject *dInstance = [aDestArray objectAtIndex:0];
            // conversion
        }
    }
    return aBool;
}

答案 1 :(得分:0)

问题是doubleCGFloatNSNumber中存储的值类型无法精确处理小数值。因此,如果设置为4.50,则可能会得到一些近似值。对于货币价值而言,这通常是不可取的,因为您需要精确的表示。您可以使用NSNumberFormatter来舍入舍入,但是如果您开始使用这些值进行数学计算或需要比百分之一更精确的数学,那么最终可能会得到不正确的数量。

我怀疑您必须进行重量级迁移才能更改CoreData实体上属性的类型。即使您没有必要,也可以这样做,以便确保转换为Decimal的值四舍五入到您选择的精度(因为它们可能是您想要的也可能不是您想要的现在在数据库中。)

听起来你的项目中有一些技术债务。你选择现在支付这笔债务还是等到它增长最终取决于你。

答案 2 :(得分:0)

您可能希望使用NSDecimalNumber,而不是NSDecimalNSDecimalstruct,而NSDecimalNumber是继承自NSNumber的Objective-C类。因此,您通常可以在NSDecimalNumber被接受的任何地方传递NSNumberNSNumberFormatter会自动格式化NSDecimalNumber个实例,如果您将格式化程序的generatesDecimalNumbers设置为YES,它会将字符串解析为NSDecimalNumber个实例。

NSDecimalNSDecimalNumber的范围大于doubleCGFloat。十进制类型存储更多有效数字并具有更大的指数范围。

我不知道自动迁移问题的答案,但我知道Core Data支持NSDecimalNumber。您可以在模型中将属性的类型设置为十进制(NSDecimalAttributeType)。