NSMutableDictionary中的对象突然变为null

Ser*_*nov 1 objective-c ios automatic-ref-counting

更新:

我添加了一个方法来检查字典中的空对象,实际上,他们找到了:

NSMutableDictionary中为空

有没有人见过这样的东西?这不是由不正确的内存管理引起的.请注意,左侧的字典对象树实际上是正确的.

结束更新

我在NSMutableDictionary启用ARC时添加了许多条目.添加其中一个后,添加的对象突然变为空.这是代码(我扩展它以确保我没有发疯):

NSMutableDictionary *base = [NSMutableDictionary dictionary];

id o = [GAConstant kTRUE];
id k = [GAClause parse:@"(x 1 1)"];
[base setObject:o forKey:k];
NSLog(@"### Added (%@ -> %@): %@", k, o, base);

o = [GAClause parse:@"(y X)"];
k = [GAClause parse:@"(x 2 X)"];
[base setObject:o forKey:k];
NSLog(@"### Added (%@ -> %@): %@", k, o, base);

o = [GAConstant kTRUE];
k = [GAClause parse:@"(y 3)"];
[base setObject:o forKey:k];
NSLog(@"### Added (%@ -> %@): %@", k, o, base);

o = [GAConstant kTRUE];
k = [GAClause parse:@"(y 6)"];
[base setObject:o forKey:k];
NSLog(@"### Added (%@ -> %@): %@", k, o, base);
Run Code Online (Sandbox Code Playgroud)

这是输出:

2013-03-25 16:10:33.546 Jungle[1978:11303] ### Added (<GAListClause: 0x75b0dc0> -> <GAConstant: 0x75b12b0>): {
    "<GAListClause: 0x75b1b00>" = "<GAConstant: 0x75b12b0>";
}
2013-03-25 16:10:33.548 Jungle[1978:11303] ### Added (<GAListClause: 0x75b2870> -> <GAListClause: 0x75b1aa0>): {
    "<GAListClause: 0x75b2270>" = "<GAListClause: 0x75b1aa0>";
    "<GAListClause: 0x75b1b00>" = "<GAConstant: 0x75b12b0>";
}
2013-03-25 16:10:33.549 Jungle[1978:11303] ### Added (<GAListClause: 0x75b2b90> -> <GAConstant: 0x75b12b0>): {
    "<GAListClause: 0x75b2d80>" = "<GAConstant: 0x75b12b0>";
    "<GAListClause: 0x75b2270>" = "<GAListClause: 0x75b1aa0>";
    "<GAListClause: 0x75b1b00>" = "<GAConstant: 0x75b12b0>";
}
2013-03-25 16:10:33.550 Jungle[1978:11303] ### Added (<GAListClause: 0x75b2f00> -> <GAConstant: 0x75b12b0>): {
    "<GAListClause: 0x75b2d80>" = "<GAConstant: 0x75b12b0>";
    "<GAListClause: 0x75b2270>" = "<GAListClause: 0x75b1aa0>";
    "<GAListClause: 0x75b1b00>" = "<GAConstant: 0x75b12b0>";
    "<GAListClause: 0x75b1d60>" = (null);
}
Run Code Online (Sandbox Code Playgroud)

该方法[GAConstant kTRUE]初始化并返回一个静态变量.[GAClause parse:]每次都返回一个新的解析对象.

很清楚为什么k变量的地址与字典的内容不对应:它复制它们.仍然不清楚null如何作为一个价值潜入.字典中null的位置随着每次运行而变化,有时候我会得到其中的两个.

看起来内存管理正在发生什么,但是什么?此处启用ARC.

这是与[GAConstant kTRUE]方法相关的代码:

+ (GAConstant *)kTRUE {
    static GAConstant *kTRUE = nil;
    static dispatch_once_t onceToken = 0;

    dispatch_once(&onceToken, ^{
        kTRUE = [[GAConstant alloc] initWithString:@"true"];
    });

    return kTRUE;
}
Run Code Online (Sandbox Code Playgroud)

有时null在字典中波动:

2013-03-25 17:09:16.426 Jungle[2294:11303] ### Added (<GAListClause: 0x7182ce0> -> <GAConstant: 0x7183430>): {
    "<GAListClause: 0x7183a30>" = "<GAConstant: 0x7183430>";
}
2013-03-25 17:09:16.428 Jungle[2294:11303] ### Added (<GAListClause: 0x75467b0> -> <GAListClause: 0x71839d0>): {
    "<GAListClause: 0x7546a30>" = (null);
    "<GAListClause: 0x7183a30>" = "<GAConstant: 0x7183430>";
}
2013-03-25 17:09:16.429 Jungle[2294:11303] ### Added (<GAListClause: 0x7546cd0> -> <GAConstant: 0x7183430>): {
    "<GAListClause: 0x7546ec0>" = "<GAConstant: 0x7183430>";
    "<GAListClause: 0x7546a30>" = "<GAListClause: 0x71839d0>";
    "<GAListClause: 0x7183a30>" = "<GAConstant: 0x7183430>";
}
2013-03-25 17:09:16.430 Jungle[2294:11303] ### Added (<GAListClause: 0x7547040> -> <GAConstant: 0x7183430>): {
    "<GAListClause: 0x75470f0>" = (null);
    "<GAListClause: 0x7546ec0>" = "<GAConstant: 0x7183430>";
    "<GAListClause: 0x7546a30>" = "<GAListClause: 0x71839d0>";
    "<GAListClause: 0x7183a30>" = "<GAConstant: 0x7183430>";
}
Run Code Online (Sandbox Code Playgroud)

这是调试器中的样子:

调试器

Sul*_*han 6

你的问题很奇怪.总之,调试器将您的字典显示为正确但objectForKey返回nil.

我在最后一小时考虑过这个问题,而且我很确定我只知道一种可能性如何发生 - 不正确hashisEqual:方法.

特别是,我认为该isEqual:方法不对称.换句话说,如果我们有

id k = [GAClause parse:@"(x 1 1)"];
Run Code Online (Sandbox Code Playgroud)

然后

[k isEqual:k]
Run Code Online (Sandbox Code Playgroud)

不一定是真的.

然后,如果您获得字典键并尝试查找它们的值(这是相同的[NSDictionary description]),则找不到值.

我相信你应该把你的断点NSLog放进去isEqual,看看比较价值时发生的事情.

另请注意,字典键被复制,因此在复制过程中可能会出现相等问题.

  • 来自[meta post](https://meta.stackoverflow.com/a/303309/5555803):) (3认同)