SlashDevSlashGnoll
SlashDevSlashGnoll

Reputation: 2321

NSDictionary returning same value for different keys

I have some Obj-C code that uses NSNumbers as keys in a dictionary. I'd found a bug that I tracked down to some very strange behavior where if the dictionary is accessed using NSDecimalNumber (a subclass of NSNumber) it would always return the same element. Here's a small program that exhibits the behavior and the NSLogs output the problem:

#define LONGNUMBER1 5846235266280328403
#define LONGNUMBER2 5846235266280328404
- (void) wtfD00d {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];

    NSNumber *key1 = [NSNumber numberWithLongLong:LONGNUMBER1];
    NSNumber *key2 = [NSNumber numberWithLongLong:LONGNUMBER2];
    dict[key1] = @"ONE";
    dict[key2] = @"TWO";

    NSNumber *decimalKey1 = [NSDecimalNumber numberWithLongLong:LONGNUMBER1];
    NSNumber *decimalKey2 = [NSDecimalNumber numberWithLongLong:LONGNUMBER2];
    NSString *value1 = dict[decimalKey1];
    NSString *value2 = dict[decimalKey2];

    NSLog(@"Number of entries in dictionary = %lu", (unsigned long)dict.count); // 2
    NSLog(@"%@", dict);  //  5846235266280328403 = ONE
                         //  5846235266280328404 = TWO
    NSLog(@"Value1 = %@, Value 2 = %@", value1, value2);   // Value1 = ONE, Value 2 = ONE
    NSLog(@"key2 = decimalKey2: %@", [key2 isEqual:decimalKey2] ? @"True" : @"False");  // key2 isEqual decimalKey2: True
    NSLog(@"decimalKey1 = decimalKey2: %@", [decimalKey1 isEqual:decimalKey2] ? @"True" : @"False");  // decimalKey1 isEqual decimalKey2: False
}

Notice that the 3rd log line shows that value1 and value2 are the same. WHY does this happen?

This came up because we have a few fields in CoreData with type Decimal and they come out of CoreData as NSNumber. We found that we had to play games to get around this strange behavior and I don't understand why it happens in the 1st place. I'd love any insight anyone can offer as to why the failed lookups.

Upvotes: 4

Views: 47

Answers (1)

Cy-4AH
Cy-4AH

Reputation: 4585

I think that when NSNumber and NSDecimalNumber are compared with each other, they are using doubleValue for comparison.

You can report bug in apple for that

I can suggest only to avoid NSNumber<->NSDecimalNumber comparison and use here:

NSString *value1 = dict[@(decimalKey1.longLongValue)];
NSString *value2 = dict[@(decimalKey2.longLongValue)];

Upvotes: 2

Related Questions