【问题标题】:ObjectForKey is returning nil sometimesObjectForKey 有时返回 nil
【发布时间】:2019-04-27 17:29:04
【问题描述】:

我正在尝试将对象设置为以键为对象的字典。测试用例工作正常,但在实际代码中,我无法获得键的值。 NSMutableDictionary 里面有键值,但是调试时返回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];
}

我正在使用initWithArray 方法创建哈希映射。

(lldb) po [dict objectForKey:key]
 nil

传入的key和字典中的key有相同的内存地址0x100ea2fa0

测试用例工作正常。但是在运行实际程序时,它会失败。

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 
}

如何解决这个问题以及为什么会出现这种随机行为?


找到失败的测试用例。

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

如果我使用调用allKeys方法返回的键,它返回nil。

【问题讨论】:

  • 你会混淆自己和其他人。属性 - 没有下划线。实例变量 - 下划线。局部变量 - 没有下划线。总是。也不例外。
  • 看起来你复制了一些至少有五年历史的代码。你到底为什么要使用可变数组进行初始化?
  • 对,数组不必是可变的。我没有复制任何代码。我自己写的:)

标签: objective-c macos nsmutabledictionary


【解决方案1】:

您没有显示任何关于 JSNumber 是什么的信息,但我敢打赌它没有正确实现 isEqualhash。因此,您无法成功地将其用作 NSDictionary 中的键。

【讨论】:

  • 我已经实现了isEqual,但我没有实现hash
  • 好了。如果字典键的类型没有正确实现hash,则字典的下标查找将无法正常工作。
  • 你为什么要实现一个名为 JSNumber 的类?使用 JSValue,或者使用 NSNumber,否则你会遇到麻烦。
  • 我正在 Objective-C 中实现另一种语言(解释器)。这些是与该语言的 AST 一起使用的数据类型类。
  • 还要确保类符合&lt;NSCopying&gt; 协议(密钥被复制)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多