我和我之前的许多程序员一样,正致力于处理金钱的应用程序。我对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 >= 0
和SELF <= 1
的验证谓词。
奇怪的是,如果我将此属性的类型更改为 Double 或 Float ,则验证谓词将更改为{正如所料,{1}}和SELF >= 0.5
。更奇怪的是,如果我在Core Data Utility Tutorial之后创建自己的数据模型,验证谓词就会正确设置,即使是十进制属性。
由于我在XCode的托管对象模型编辑器中找不到任何解决此问题的方法,因此我已将以下代码(SELF <= 1.2
和begin workaround
注释 - 添加到我的应用程序委托的{ {1}}方法(这是在创建使用Core Data的新项目时默认情况下XCode提供的相同应用程序委托)。请注意,我添加了一个约束来保持end workaround
实体的managedObjectModel
属性大于0。
Transaction
您应该能够使用以下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
方法按照以下步骤使用此代码。
DecimalTest_AppDelegate
。managedObjectContext
插座连接到您的应用程序代表。DebugController
)添加到您的用户界面,并将控制器的appDelegate
插座连接到它。NSTextField
操作。debugLabel
操作相关联的按钮。这会将您的托管对象模型的约束打印到updateLabel
,并应说明我在此处描述的行为。DebugController.h
updateLabel
DebugController.m
debugLabel
谢谢大家。
答案 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)
这是一个关于你的问题的故事 - 我想
请记住小数不是小数 - 你会把小数点放在哪里?
浮点数内部称为尾数......