John Doe
John Doe

Reputation: 2491

ObjectForKey is returning nil sometimes

I am trying to set an object to a dictionary with key as an object. The test cases works fine, but within the actual code, I am not able to get the value for the key. The NSMutableDictionary has the key value in it, but when debugging it returns nil.

@implementation JSHashMap {
    NSMutableDictionary *dict;
}

- (instancetype)initWithArray:(NSMutableArray *)array {
    self = [super init];
    if (self) {
        dict = [self fromArray:array];
    }
    return self;
}

- (NSMutableDictionary *)fromArray:(NSMutableArray *)array {
    NSMutableDictionary* _dict = [NSMutableDictionary new];
    NSUInteger i = 0, len = [array count];
    if (len % 2 != 0) {
        error(@"JSError: Odd number of elements in the array.");
        return _dict;
    }
    for (i = 0; i < len; i = i + 2) {
        [_dict setObject:array[i + 1] forKey:array[i]];
        assert([_dict objectForKey:array[i]] != nil);
    }
    debug(@"%@", _dict);
    return _dict;
}

- (JSData *)objectForKey:(id)key {
    return [dict objectForKey:key];
}

I am creating the hash map using the initWithArray method.

(lldb) po [dict objectForKey:key]
 nil

The key passed in and the key in the dictionary has the same memory address 0x100ea2fa0.

screenshot - debug variables

The test cases works fine though. But the when running the actual program, it fails.

NSMutableDictionary *dict = [NSMutableDictionary new];
JSNumber *val = [[JSNumber alloc] initWithInt:1];
JSNumber *key = [[JSNumber alloc] initWithInt:2];
[dict setObject:val forKey:key];
JSData * ret = [dict objectForKey:key];
XCTAssertNotNil(ret);
XCTAssertEqualObjects([ret dataType], @"JSNumber");
JSHashMap *hm = [[JSHashMap alloc] initWithArray:[@[key, val] mutableCopy]];
JSData * ret1 = [hm objectForKey:key];
XCTAssertNotNil(ret1);
XCTAssertEqualObjects([ret1 dataType], @"JSNumber");
JSHashMap *dict = (JSHashMap *)ast;
NSArray *keys = [dict allKeys];
NSUInteger i = 0;
NSUInteger len = [keys count];
for (i = 0; i < len; i++) {
    id key = keys[i];
    JSData *val = (JSData *)[dict objectForKey:key];
    // Issue -> val is getting nil 
}

How to fix this and why is this random behaviour?


Found the failing test case.

NSArray *keys = [hm allKeys];
XCTAssertTrue([keys count] == 1);
JSData *ret = [hm objectForKey:keys[0]];
XCTAssertNotNil(ret);

If I use the key returned from calling allKeys method, it returns nil.

Upvotes: 1

Views: 469

Answers (1)

matt
matt

Reputation: 535139

You have not shown any information about what JSNumber is, but I am betting that it does not implement isEqual and hash correctly. Thus, you cannot successfully use it as a key in an NSDictionary.

Upvotes: 3

Related Questions