更新
我添加了一个检查字典中空对象的方法,实际上,它们被找到了:
有没有人见过这样的东西?这不是由不正确的内存管理引起的。请注意,左侧的字典对象树实际上是正确的。
结束更新
我在启用ARC的情况下向NSMutableDictionary
添加了一些条目。添加其中一个后,添加的对象突然变为空。这是代码(我扩展它以确保我没有发疯):
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);
这是输出:
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);
}
方法[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;
}
有时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>";
}
以下是调试器中的内容:
答案 0 :(得分:6)
你的问题很奇怪。总之,调试器会将您的字典显示为正确,但objectForKey
会返回nil
。
我在过去一小时内一直在思考这个问题,我很确定我只知道如何发生这种情况 - 不正确的hash
或isEqual:
方法。
特别是,我认为isEqual:
方法不对称。换句话说,如果我们有
id k = [GAClause parse:@"(x 1 1)"];
然后
[k isEqual:k]
不一定是真的。
然后,如果您获得字典键并尝试查找它们的值(与[NSDictionary description]
相同),则找不到值。
我相信您应该将断点/ NSLog
放入isEqual
并观察比较值时发生的情况。
另请注意,复制了字典键,因此在复制过程中可能会出现相等问题。