一个更简单的解决方案可能是在您的费用类上实现另一种方法,该方法可为您提供适当的计算量。
E.g.
- (NSDecimalNumber *) calculatedExpenseAmount {
NSDecimalNumber *actualAmount = self.expenseAmount;
// Pseudo-code begins
if (self.expenseCategory != nil) {
actualAmount = self.expenseAmount * self.expenseCategory.unitRate;
}
return actualAmount;
}
我添加到我以前的答案。
如果您希望避免牵扯每个托管对象,那么可以使用NSDictionary结果查询来提取expenseAmount和expenseCategory.unitRate值。
- (NSDecimalNumber *) totalExpenses
{
// Fetch all of the expense amounts and unit rate of any related category.
NSFetchRequest *request = ...;
[request setManagedObjectContext:<...>];
[request setEntity:<ExpenseAccountDescription>];
[request setResultType:NSDictionaryResultType];
NSArray *props = [NSArray arrayWithObjects:@"expenseAmount", @"category.unitRate", nil];
[request setPropertiesToFetch:props];
NSArray *amounts = [request executeRequest:...];
// amounts is an array of dictionaries, each hold the desired property values.
// Loop and sum the individual amounts
NSDecimal *total = [[NSDecimalNumber zero] decimalNumber];
NSAutoreleasePool *pool = nil; // contain the mess
NSCalculationError err = NSCalculationNoError;
for (NSDictionary *result in amounts)
{
pool = [NSAutoreleasePool new];
NSDecimal newTotal = [[NSDecimalNumber zero] decimalNumber];
NSDecimalNumber *expenseAmount = [result valueForKeyPath:@"expenseAmount"];
NSDecimalNumber *unitRate = [result valueForKeyPath:@"category.unitRate"];
if (unitRate != nil) {
// do the unit rate multiplication and accumulate the result in the total
NSDecimal calculated = [[NSDecimalNumber zero] decimalNumber];
err = NSDecimalMultiply (&calculated, [expenseAmount decimalNumber], [unitRate decimalNumber], NSRoundBankers);
if (err == NSCalculationNoError) {
err = NSDecimalAdd (&newTotal, total, calculated, NSRoundBankers);
}
}
else {
// just accumulate the result in the total
err = NSDecimalAdd (&newTotal, total, [expenseAmount decimalNumber], NSRoundBankers);
}
// Keep the new total
NSDecimalCopy(&total, newTotal);
[pool drain];
}
return [NSDecimalNumber decimalNumberWithDecimal:total];
}
如果您有10000个费用条目,则此提取和计算可能会少于1MB的RAM。仪器将是你的朋友测量。
谢谢你的这个问题。我有一个类似的问题,NSExpression不适合我 - 我正在使用双打和时间戳,由于某种原因,divide:by:函数会产生奇怪的结果。我很好奇你的最终解决方案,因为我还需要在计算中包含多条记录。 – 2014-01-24 20:40:35