Problems with NSDecimalNumber Arithmetic when NSDecimalNumbers are stored in NSDictionary from NSExpression Core Data Fetch

StackOverflow https://stackoverflow.com/questions/18414838

I have been experimenting trying to learn how to use NSExpressions to fetch aggregate info from Core Data. I have the fetch working properly but I'm having trouble trying to parse the resulting data for processing. I'm sure I must be missing something but I can't figure out what it is. I'm fetching the sum of an attribute on some entities and I have this part right. Then I want to do some math on the results but I am not getting the desired results.

Here is my sample code

[_mainContext save:nil];
NSMutableDictionary *accountBalances = [[NSMutableDictionary alloc] init];
NSFetchRequest* request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"AccountTransaction"
                             inManagedObjectContext:_mainContext];

// build an expression to calculate the sum
NSExpressionDescription* totalOfTransactionsDescription = [[NSExpressionDescription alloc] init];

NSExpression *keyExpression = [NSExpression expressionForKeyPath:@"amount"];
NSExpression *theExpression = [NSExpression expressionForFunction:@"sum:"
                                                        arguments:@[keyExpression]];

[totalOfTransactionsDescription setName:@"totalOfTransactions"];
[totalOfTransactionsDescription setExpression:theExpression];
[totalOfTransactionsDescription setExpressionResultType:NSFloatAttributeType];

// we want the results in a dictionary
request.resultType = NSDictionaryResultType;
request.propertiesToFetch = @[totalOfTransactionsDescription];
NSArray* results;
NSDictionary* fetchResultsDictionary;
NSDecimalNumber *total;

// credits
request.predicate = [NSPredicate predicateWithFormat:@"isCredit == %@",[NSNumber numberWithBool:YES]];
results = [_mainContext executeFetchRequest:request error:nil];
fetchResultsDictionary = [results objectAtIndex:0];
total = [fetchResultsDictionary objectForKey:@"totalOfTransactions"];
[accountBalances setObject:total forKey:@"postedCredits"];

// debits
request.predicate = [NSPredicate predicateWithFormat:@"isCredit == %@",[NSNumber numberWithBool:NO]];
results = [_mainContext executeFetchRequest:request error:nil];
fetchResultsDictionary = [results objectAtIndex:0];
total = [fetchResultsDictionary objectForKey:@"totalOfTransactions"];
[accountBalances setObject:total forKey:@"postedDebits"];


// build an account balance
NSDecimalNumber *startingBalance = [NSDecimalNumber decimalNumberWithString:@"100.00"];
NSDecimalNumber *currentBalance = startingBalance;

// add deposits
currentBalance = [currentBalance decimalNumberByAdding:[accountBalances objectForKey:@"postedCredits"]];

// subtract debits
currentBalance = [currentBalance decimalNumberBySubtracting:[accountBalances objectForKey:@"postedDebits"]];

[accountBalances setObject:currentBalance forKey:@"currentBalance"];

NSLog(@"%@", accountBalances);

Here is my console log

2013-08-23 23:56:35.775 NSExpressionCoreDataTestApp[5162:907] {
    currentBalance = 100;
    postedCredits = 300;
    postedDebits = 25;
}

Now I'm no rocket scientist, but $100+$300-$25 = $375. My currentBalance is always $100. Also based on my sample data postedCredits & postedDebits are correct but nothing seems to be getting added to or subtracted from the initial starting balance. I'm sure I must need to type cast the results somewhere but I've tried before the fetch result gets added to the dictionary & before the addition or subtraction takes place. I've even tried [NSDecimalNumber NSDecimalNumberWithString:] after pulling them from the dictionary before operating on them.

If someone could point me in the right direction here I'd much appreciate it. Thanks in advance!!

有帮助吗?

解决方案

After looking with fresh eyes this morning I realized the answer was staring me in the face.

[totalOfTransactionsDescription setExpressionResultType:NSFloatAttributeType];

should have been

[totalOfTransactionsDescription setExpressionResultType:NSDecimalAttributeType];

That cleared it right up. :-)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top