Một giải pháp đơn giản hơn có thể là triển khai phương pháp khác trên lớp Chi phí cung cấp cho bạn số tiền được tính thích hợp.
Ví dụ:
- (NSDecimalNumber *) calculatedExpenseAmount {
NSDecimalNumber *actualAmount = self.expenseAmount;
// Pseudo-code begins
if (self.expenseCategory != nil) {
actualAmount = self.expenseAmount * self.expenseCategory.unitRate;
}
return actualAmount;
}
tôi thêm vào câu trả lời trước đây của tôi.
Nếu bạn muốn tránh kéo vào mọi đối tượng được quản lý, bạn có thể sử dụng truy vấn kết quả NSDictionary để chỉ cần rút ra các giá trị costAmount và costCategory.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];
}
Nếu bạn có 10.000 mục nhập chi phí, quá trình tìm nạp và tính toán này có thể nhỏ hơn 1MB RAM. Dụng cụ sẽ là bạn của bạn trong việc đo lường điều đó.
Nguồn
2011-01-20 08:32:56
Cảm ơn bạn đã đặt câu hỏi này. Tôi có một vấn đề tương tự và NSExpression đã không làm việc cho tôi - Tôi đang làm việc với đôi và dấu thời gian và vì một lý do nào đó phân chia: bởi: chức năng tạo ra kết quả lạ. Tôi tò mò về giải pháp cuối cùng của bạn vì tôi cũng cần bao gồm nhiều hơn một bản ghi duy nhất trong tính toán của mình. –