通过核心数据计算小数值的总和无法正常工作?

发布于 2024-08-10 16:18:35 字数 2247 浏览 6 评论 0原文

我第一次在这一轮发帖,所以如果我没有正确遵守所有规则,请多多包涵。

我正在为 iPhone (OS 3.1) 编写一个应用程序,并尝试编写一些代码来添加小数。我有一个名为 SimpleItem 的核心数据实体,带有 amount 属性。这是我编写的测试用例:

// Create and configure objects
    SimpleItem *si1 = [self createSimpleItem:@"si1"];
    si1.amount = [NSDecimalNumber decimalNumberWithMantissa:1000 exponent:0 isNegative:NO];
    SimpleItem *si2 = [self createSimpleItem:@"s12"];
    si2.amount = [NSDecimalNumber decimalNumberWithMantissa:2000 exponent:0 isNegative:NO];
    // Need to save prior to fetching results with NSDictionaryResultType (known limitation)
    [self save]; 

    // Describe fetch request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"SimpleItem" inManagedObjectContext:self.context];
    [request setEntity:entityDescription];
    [request setResultType:NSDictionaryResultType];

    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"amount"];
//  For whatever reason, evaluating this expression here is absolutely not working. Probably decimals aren't handled properly.
    NSExpression *sumAmountExpression = [NSExpression 
                                         expressionForFunction:@"max:"
                                         arguments:[NSArray arrayWithObject:keyPathExpression]];

    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName:@"amount"];
    [expressionDescription setExpression:sumAmountExpression];
    [expressionDescription setExpressionResultType:NSDecimalAttributeType];
    [request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

    // Fetch the amounts
    NSError *error = nil;
    NSArray *array = [self.context executeFetchRequest:request error:&error];

如果我通过 otest 执行此代码并对其进行调试,则在执行获取请求时会出现异常:“-[NSDecimalNumber count]:无法识别的选择器已发送到实例。”

不过,仅在没有聚合函数的情况下评估 keyPathExpression 就可以了。

参考文档显示了完全相同的示例,所以我想知道我做错了什么。或者这可能只是一个错误?

一切顺利, 哈拉尔德

first time I post to this round, so please bear with me if I don't follow all the rules properly.

I am writing an app for the iPhone (OS 3.1) and am trying to write some code which lets me add decimals. I have a Core Data entity called SimpleItem with a amount attribute. Here is the test case I wrote:

// Create and configure objects
    SimpleItem *si1 = [self createSimpleItem:@"si1"];
    si1.amount = [NSDecimalNumber decimalNumberWithMantissa:1000 exponent:0 isNegative:NO];
    SimpleItem *si2 = [self createSimpleItem:@"s12"];
    si2.amount = [NSDecimalNumber decimalNumberWithMantissa:2000 exponent:0 isNegative:NO];
    // Need to save prior to fetching results with NSDictionaryResultType (known limitation)
    [self save]; 

    // Describe fetch request
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"SimpleItem" inManagedObjectContext:self.context];
    [request setEntity:entityDescription];
    [request setResultType:NSDictionaryResultType];

    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"amount"];
//  For whatever reason, evaluating this expression here is absolutely not working. Probably decimals aren't handled properly.
    NSExpression *sumAmountExpression = [NSExpression 
                                         expressionForFunction:@"max:"
                                         arguments:[NSArray arrayWithObject:keyPathExpression]];

    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName:@"amount"];
    [expressionDescription setExpression:sumAmountExpression];
    [expressionDescription setExpressionResultType:NSDecimalAttributeType];
    [request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

    // Fetch the amounts
    NSError *error = nil;
    NSArray *array = [self.context executeFetchRequest:request error:&error];

If I execute this code through otest and debug it, I get an exception when the fetch request is executed: "-[NSDecimalNumber count]: unrecognized selector sent to instance."

Just evaluating the keyPathExpression without the aggregate function works fine, though.

The reference documentation shows exactly the same example so I'm wondering what I am doing wrong. Or could this be just a bug?

All the best,
Harald

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

两仪 2024-08-17 16:18:35

将给定的源代码复制到新的 iPhone 项目并在模拟器中运行它在这里效果很好。我在 Snow Leopard 上针对 3.1.2 SDK 进行编译。

这是我用于数据模型的内容:

模型描述http://homepage.mac.com/aclark78/.Public/Pictures/test%20model.png

肯定还有其他原因导致了您的问题。您能描述您的模型或进一步简化它吗?

Copying your given source to a new iPhone project and running that in the simulator worked fine here. I was compiling against the 3.1.2 SDK on Snow Leopard.

This is what I used for the data model:

model description http://homepage.mac.com/aclark78/.Public/Pictures/test%20model.png

There must be something else going on causing your issue. Can you describe your model or simplify it further?

北音执念 2024-08-17 16:18:35

我想我以前也遇到过这个问题。 IIRC,问题是您已将获取结果类型设置为NSDictionaryResultType,但您在NSArray中接收它。尝试将获取结果类型切换为 NSManagedObjectResultType ,它会返回一个数组。 文档中的所有示例都使用默认的 NSManagedObjectResultType

无论如何,错误消息显然是由于向 NSDecimal 对象发送数组的 count 消息而导致的。您可以通过将结果捕获到 id 中来确认这一点。例如:

id *genericObj = [self.context executeFetchRequest:request error:&error];  
NSLog("returned object=%@",genericObj);
NSLog("returned object class=%@",[genericObj class]);

I think I had this problem before. IIRC, the problem is that you've set your fetch result type to NSDictionaryResultType but you're receiving it in an NSArray. Try switching the fetch result type to NSManagedObjectResultType which does return an array. All the examples in the docs use the default NSManagedObjectResultType.

In any case, the error message clearly results from an NSDecimal object being sent an array's count message. You could confirm this by trapping the result in an id. eg:

id *genericObj = [self.context executeFetchRequest:request error:&error];  
NSLog("returned object=%@",genericObj);
NSLog("returned object class=%@",[genericObj class]);
爱冒险 2024-08-17 16:18:35

谢谢你让我知道。问题是我实际上不想使用托管对象。毕竟,我只对金额感兴趣,这就是我从字典中得到的结果。

另外,尝试调查您所描述的问题并不起作用,因为执行获取请求立即失败,并且我没有得到任何返回。

还有其他想法吗?还有其他可能获得汇总值吗?有什么“最佳实践”吗?目前,我执行以下操作(上面代码的延续):

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[表达式描述集名称:@"金额"];
[表达式描述 setExpression:keyPathExpression];
[表达式描述 setExpressionResultType:NSDecimalAttributeType];
[请求 setPropertiesToFetch:[NSArray arrayWithObject:表达式描述]];

// Fetch the amounts
NSError *error = nil;
NSArray *array = [self.context executeFetchRequest:request error:&error];
if (array == nil) {
    STFail(@"Fetch request could not be completed: %@", [error localizedDescription]);
}
STAssertEquals([array count], (NSUInteger) 2, @"Number of fetched objects != 2");

// Manually calculate the sum
NSDecimalNumber *sum = nil;
for (NSDictionary * dictionary in array) {
    NSDecimalNumber *amount = (NSDecimalNumber *) [dictionary valueForKey:@"amount"];
    if (!sum) {
        sum = amount;
    } else {
        sum = [sum decimalNumberByAdding:amount];
    }
}
STAssertNotNil(sum, @"Sum is nil");
STAssertTrue([sum isEqualToNumber:[NSDecimalNumber decimalNumberWithMantissa:3000 exponent:0 isNegative:NO]], 
               @"Sum != 3000: %@", sum);

问候,
哈拉尔德

Thanks for letting me know. The thing is that I actually don't want to use managed objects. After all, I am interested in the amounts only and this is what I get with the dictionary.

Also, trying to investigate the issue as you described didn't work as executing the fetch request immediately fails and I don't get anything back.

Any other ideas? Is there any other possibility to get aggregate values? Any "best practices"? At the moment I do the following (continuation of the code above):

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"amount"];
[expressionDescription setExpression:keyPathExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

// Fetch the amounts
NSError *error = nil;
NSArray *array = [self.context executeFetchRequest:request error:&error];
if (array == nil) {
    STFail(@"Fetch request could not be completed: %@", [error localizedDescription]);
}
STAssertEquals([array count], (NSUInteger) 2, @"Number of fetched objects != 2");

// Manually calculate the sum
NSDecimalNumber *sum = nil;
for (NSDictionary * dictionary in array) {
    NSDecimalNumber *amount = (NSDecimalNumber *) [dictionary valueForKey:@"amount"];
    if (!sum) {
        sum = amount;
    } else {
        sum = [sum decimalNumberByAdding:amount];
    }
}
STAssertNotNil(sum, @"Sum is nil");
STAssertTrue([sum isEqualToNumber:[NSDecimalNumber decimalNumberWithMantissa:3000 exponent:0 isNegative:NO]], 
               @"Sum != 3000: %@", sum);

Regards,
Harald

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文