Ios 如何将核心数据中每个对象的十进制值相加,得出一个总数?
我试图做的是循环遍历我的核心数据对象,并添加每个项目的价格,然后返回总数。我下面的代码不断崩溃,我不知道为什么。以前我使用浮点数,但有人建议我使用NSDecimalNumber,因为它更准确。所以我开始转换我的代码来使用它 循环对象并添加价格然后返回总计的代码:Ios 如何将核心数据中每个对象的十进制值相加,得出一个总数?,ios,objective-c,cocoa-touch,core-data,nsdecimalnumber,Ios,Objective C,Cocoa Touch,Core Data,Nsdecimalnumber,我试图做的是循环遍历我的核心数据对象,并添加每个项目的价格,然后返回总数。我下面的代码不断崩溃,我不知道为什么。以前我使用浮点数,但有人建议我使用NSDecimalNumber,因为它更准确。所以我开始转换我的代码来使用它 循环对象并添加价格然后返回总计的代码: + (NSDecimalNumber *)totalPriceOfItems:(NSManagedObjectContext *)managedObjectContext { NSError *error = nil;
+ (NSDecimalNumber *)totalPriceOfItems:(NSManagedObjectContext *)managedObjectContext
{
NSError *error = nil;
NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];
// Get fetched objects and store in NSArray
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (BagItem *bagItem in fetchedObjects) {
// NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithString:[bagItem price]];
// NSString *price = [[[bagItem price] componentsSeparatedByCharactersInSet:
// [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
// componentsJoinedByString:@""];
totalPrice = [totalPrice decimalNumberByAdding:[bagItem price]];
NSLog(@"total: %@", totalPrice);
}
return totalPrice;
}
** Terminating app due to uncaught exception 'NSDecimalNumberOverflowException', reason: 'NSDecimalNumber overflow exception'
*** First throw call stack:
错误:
+ (NSDecimalNumber *)totalPriceOfItems:(NSManagedObjectContext *)managedObjectContext
{
NSError *error = nil;
NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];
// Get fetched objects and store in NSArray
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (BagItem *bagItem in fetchedObjects) {
// NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithString:[bagItem price]];
// NSString *price = [[[bagItem price] componentsSeparatedByCharactersInSet:
// [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
// componentsJoinedByString:@""];
totalPrice = [totalPrice decimalNumberByAdding:[bagItem price]];
NSLog(@"total: %@", totalPrice);
}
return totalPrice;
}
** Terminating app due to uncaught exception 'NSDecimalNumberOverflowException', reason: 'NSDecimalNumber overflow exception'
*** First throw call stack:
我不知道为什么会出现溢出,因为
NSDecimal
的范围比浮点的范围大(不过它没有双精度的范围大)
不管是什么原因,滚动自己的循环并不是从核心数据请求聚合结果的正确方法:只要代码提供有关如何聚合数据的正确说明,API允许您请求数据库为您合计价格。您应该能够通过传递聚合表达式直接从核心数据中获取总计,如下所示:
NSExpression *totalPriceExpr = [NSExpression expressionForFunction:@"sum:"
arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:@"Price"]]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"totalPrice"];
[expressionDescription setExpression:totalPriceExpr];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
fetchedObjects
将包含一个带有计数的项目。我不确定为什么会出现溢出,因为NSDecimal
的范围大于float
(但它没有双精度的范围宽)
不管是什么原因,滚动自己的循环并不是从核心数据请求聚合结果的正确方法:只要代码提供有关如何聚合数据的正确说明,API允许您请求数据库为您合计价格。您应该能够通过传递聚合表达式直接从核心数据中获取总计,如下所示:
NSExpression *totalPriceExpr = [NSExpression expressionForFunction:@"sum:"
arguments:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:@"Price"]]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"totalPrice"];
[expressionDescription setExpression:totalPriceExpr];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"BagItem"];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
fetchedObjects
将包含一个带有计数的项目。获取的例外情况是,您试图添加两个非常大的数字,而表示该数字所需的位数对于NSDecimalNumber来说太大。您的数字可能不是问题所在,而是您声明totalPrice变量的方式
这一行应该改一下
NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];
到
NSDecimalNumber是围绕NSDecimal(本身围绕NSValue)的包装器,不为其init方法提供默认值。如果它真的这样做了,值应该是多少?一,零,十万?它实际上默认为NaN。本质上,您的起始值可能会占用所有可用字节,并且无论何时添加,都会得到异常
NSDecimalNumber内置了处理溢出和其他数学错误(例如被零除)的机制。您可以通过使用setBehavior方法调用提供新的行为对象来更改默认行为。您得到的例外情况是,您试图添加两个非常大的数字,而表示它所需的位数对于NSDecimalNumber来说太大。您的数字可能不是问题所在,而是您声明totalPrice变量的方式
这一行应该改一下
NSDecimalNumber *totalPrice = [[NSDecimalNumber alloc] init];
到
NSDecimalNumber是围绕NSDecimal(本身围绕NSValue)的包装器,不为其init方法提供默认值。如果它真的这样做了,值应该是多少?一,零,十万?它实际上默认为NaN。本质上,您的起始值可能会占用所有可用字节,并且无论何时添加,都会得到异常
NSDecimalNumber内置了处理溢出和其他数学错误(例如被零除)的机制。您可以通过使用setBehavior方法调用提供新的行为对象来更改默认行为。NSDecimalNumber*totalPrice=[[NSDecimalNumber alloc]initWithInt:0];为我工作过。NSDecimalNumber*totalPrice=[[NSDecimalNumber alloc]initWithInt:0];为我工作,很有帮助。没有意识到核心数据能够做到这一点。非常有用。没有意识到核心数据能够做到这一点。