XCode是否为核心数据十进制属性设置了“最小值”和“最大值”?

时间:2011-05-17 16:19:35

标签: objective-c xcode cocoa core-data

背景

我和我之前的许多程序员一样,正致力于处理金钱的应用程序。我对Cocoa编程比较陌生,但在阅读完手册之后,我决定尝试使用Core Data,因为它提供了许多我想要的功能,应该让我免于重新发明轮。无论如何,我的问题与我是否应该使用核心数据没有任何关系:它与核心数据和XCode本身的行为有关。

更新:我向Apple提交了一份错误报告,并获悉它与问题ID 9405079重复。他们知道这个问题,但我不知道他们何时或是否会去解决它。

问题

由于某些我无法理解的原因, XCode在我的托管对象模型中编辑Decimal属性时会出现 Min Value Max Value 约束。< / em>(我正在使用the reasons described here的十进制属性。)

假设我有一个名为value的Decimal属性的Core Data实体(这只是为了说明;我也使用了其他属性名称)。我希望它的值大于0,但因为XCode只允许我指定最小值(包括),所以我将最小值设置为等于0.01。令我惊讶的是,这会产生SELF >= 0的验证谓词!当我更改最小值时,我得到相同的结果:所有小数值都被截断(最小值被覆盖)。最大值具有相同的行为。

作为示例,以下屏幕截图中的value属性将生成SELF >= 0SELF <= 1的验证谓词。

value configured in XCode

奇怪的是,如果我将此属性的类型更改为 Double Float ,则验证谓词将更改为{正如所料,{1}}和SELF >= 0.5。更奇怪的是,如果我在Core Data Utility Tutorial之后创建自己的数据模型,验证谓词就会正确设置,即使是十进制属性

原始解决方法

由于我在XCode的托管对象模型编辑器中找不到任何解决此问题的方法,因此我已将以下代码(SELF <= 1.2begin workaround注释 - 添加到我的应用程序委托的{ {1}}方法(这是在创建使用Core Data的新项目时默认情况下XCode提供的相同应用程序委托)。请注意,我添加了一个约束来保持end workaround实体的managedObjectModel属性大于0。

Transaction

问题

  1. 这是否真的是XCode如何为Core Data的托管对象模型中的十进制属性生成验证谓词的错误?
  2. 如果是这样,有没有比我在这里描述的方法更好的解决方法?
  3. Repro Code

    您应该能够使用以下amount类的示例代码重现此问题,该类将托管对象模型中每个属性的约束打印到标签。此代码做出以下假设。

    • 您有一个名为- (NSManagedObjectModel *)managedObjectModel { if (managedObjectModel) return managedObjectModel; managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain]; // begin workaround NSEntityDescription *transactionEntity = [[managedObjectModel entitiesByName] objectForKey:@"Transaction"]; NSAttributeDescription *amountAttribute = [[transactionEntity attributesByName] objectForKey:@"amount"]; [amountAttribute setValidationPredicates:[NSArray arrayWithObject:[NSPredicate predicateWithFormat:@"SELF > 0"]] withValidationWarnings:[NSArray arrayWithObject:@"amount is not greater than 0"]]; // end workaround return managedObjectModel; }
    • 的应用程序委托
    • 您的申请代表有一个DebugController方法
    • 您的托管对象模型名为“Wallet”

    按照以下步骤使用此代码。

    1. 在Interface Builder中实例化DecimalTest_AppDelegate
    2. 将控制器的managedObjectContext插座连接到您的应用程序代表。
    3. 将包装标签(DebugController)添加到您的用户界面,并将控制器的appDelegate插座连接到它。
    4. 在您的用户界面中添加一个按钮,并将其选择器连接到控制器的NSTextField操作。
    5. 启动您的应用程序,然后按下与debugLabel操作相关联的按钮。这会将您的托管对象模型的约束打印到updateLabel,并应说明我在此处描述的行为。
    6. DebugController.h

      updateLabel

      DebugController.m

      debugLabel

      谢谢大家。

3 个答案:

答案 0 :(得分:2)

我做了另一项测试,我怀疑它与compare:NSNumber的{​​{1}}方法有关。

NSDecimalNumber

输出是:

NSDecimalNumber * dn = [NSDecimalNumber decimalNumberWithString:@"1.2"];

if ([dn compare:[NSNumber numberWithFloat:1.2]]==NSOrderedSame) {
        NSLog(@"1.2==1.2");
    }else{
        NSLog(@"1.2!=1.2");
    }

    if ([[NSNumber numberWithFloat:1.2] compare:dn]==NSOrderedSame) {
        NSLog(@"1.2==1.2");
    }else{
        NSLog(@"1.2!=1.2");
    }

编辑:以下解决方法最初是我在问题中添加的评论,最终会被改编为问题正文。

使用2011-06-08 14:39:27.835 decimalTest[3335:903] 1.2==1.2 2011-06-08 14:39:27.836 decimalTest[3335:903] 1.2!=1.2 ,您可以实现接近默认行为的行为(described here)。

例如(摘自问题正文,由OP Chris撰写):

-(BOOL)validate<key>:(id *)ioValue error:(NSError **)outError

答案 1 :(得分:0)

这是一个非常长的镜头,但你尝试过1,2而不是1.2?

答案 2 :(得分:0)

这很重要:http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=86013D0FEFFA6CD1A626176C5D4EF9E2?doi=10.1.1.102.244&rep=rep1&type=pdf

这是一个关于你的问题的故事 - 我想

请记住小数不是小数 - 你会把小数点放在哪里?

浮点数内部称为尾数......