如何有效地使用NSMutableDictionaries作为字典的键?

Vol*_*ort 1 objective-c nsdictionary nsmutabledictionary ios

我想将NSMutableDictionary实例用作另一个实例的键NSMutableDictionary.

    NSMutableDictionary *stuff = [NSMutableDictionary dictionary];
    NSMutableDictionary *first = [NSMutableDictionary dictionary];
    [stuff setObject:@"A" forKey:first];
    NSLog(@"I GOT %@",[stuff objectForKey:first]);
Run Code Online (Sandbox Code Playgroud)

@"A"正如所料,这输出很好.

但是,如果之后我修改了first对象中的值,如下所示:

[first setObject:@"C" forKey:@"Something"];
Run Code Online (Sandbox Code Playgroud)

我现在无法得到@"A":

NSLog(@"I GOT %@",[stuff objectForKey:first]);
Run Code Online (Sandbox Code Playgroud)

哪个输出nil.

我假设objectForKey将密钥的内存地址与字典中的现有密钥进行比较 - 因为尽管更改了字典的内部值(我认为),这样的内存地址不会改变,但我预计它会起作用.

我设法让它使用不同的方法 - 通过使用NSStrings 代替键 - 字符串的值将是内存地址本身,如下所示:

    NSMutableDictionary *stuff = [NSMutableDictionary dictionary];
    NSMutableDictionary *first = [NSMutableDictionary dictionary];
    [stuff setObject:@"A" forKey:[NSString stringWithFormat:@"%p",first]];
    [first setObject:@"C" forKey:@"Something"];
    NSLog(@"I GOT %@",[NSString stringWithFormat:@"%p",first]);
Run Code Online (Sandbox Code Playgroud)

哪个工作,打印@"A".

我的问题:

  • 为什么我原来的方法不起作用?

Jos*_*ell 5

字典在设置时获取其密钥的副本(并且该副本是不可变的).然后,当您改变用于键的对象时,它和副本不再相等:NSDictionary使用hash和isEqual:检查键时.(集合不会在这些方法中使用对象的地址来确定它们是否相等,即使它们已经相同,副本和原始地址也有不同的地址.)因此,您无法检索该值.如果您将字典重新改变为原来的字体,则检索将成功.

你提出的字符串技巧是一个很好的解决方法; 你也可以用它+[NSValue valueWithNonRetainedObject:]来达到这个目的.由于密钥字典的地址在您改变它时不会改变,因此您仍然可以获得相同的值以便在之后查找.