NSMutableDictionary奇怪的问题

时间:2011-03-07 07:26:09

标签: objective-c cocoa release

假设我有一个包含两个NSMutableDictionary的类。

@interface GameDataManager : CCNode {

    NSMutableDictionary *worldInfoDictionary;
    NSMutableDictionary *levelInfoDictionary;
}

@property (nonatomic, retain) NSMutableDictionary *worldInfoDictionary;
@property (nonatomic, retain) NSMutableDictionary *levelInfoDictionary;

我在应用程序启动时从plist加载数据:

-(BOOL) readApplicationData:(NSString *)fileName
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];
    NSData *myData = [[[NSData alloc] initWithContentsOfFile:appFile] autorelease];

    if (myData == nil) {

       return NO;
    }

    NSKeyedUnarchiver *un = [[NSKeyedUnarchiver alloc] initForReadingWithData:myData];
    NSMutableDictionary *dic = [un decodeObjectForKey:@"GameData"];

    self.worldInfoDictionary = [dic objectForKey:@"WorldInfoDictionary"];
    self.levelInfoDictionary = [dic objectForKey:@"LevelInfoDictionary"];

for (int i = 1; i <= 10; i++) {

           WorldInfoData * w = [worldInfoDictionary objectForKey:
                             [[[NSString alloc] initWithFormat:@"World%d", i] autorelease]];
    NSLog(@"%d", w.worldNum);
    [w release];
}

    [un finishDecoding];
    [un release];
    return YES; 
}

接下来的两行:

self.worldInfoDictionary = [dic objectForKey:@"WorldInfoDictionary"];
self.levelInfoDictionary = [dic objectForKey:@"LevelInfoDictionary"];

我可以看到两个词典中的值/键的数量是正确的。

然后我尝试打印除了app之外的每个对象的所有“worldNum”值 crahed:

2011-03-07 15:18:21.819 [1267:207] 1
2011-03-07 15:18:21.820 [1267:207] 2
2011-03-07 15:18:21.821 [1267:207] 3
2011-03-07 15:18:21.823 [1267:207] 4
2011-03-07 15:18:21.831 [1267:207] 5
2011-03-07 15:18:21.832 [1267:207] 6
2011-03-07 15:18:21.832 [1267:207] 7
2011-03-07 15:18:21.833 [1267:207] 8
2011-03-07 15:18:21.834 [1267:207] 9
2011-03-07 15:18:21.834 [1267:207] 10
Stack dump:
0.  Running pass 'Sparse Conditional Constant Propagation' on function '@gleLLVMVecProjectionTransform2'

如果我取消注释这一行:

[un release];

该应用程序运行良好,没有崩溃。

任何人都可以向我解释一下,非常感谢^ _ ^

感谢所有答案。

但是如果我删除了用于输出一些信息的代码行:

for (int i = 1; i <= 10; i++) {

           WorldInfoData * w = [worldInfoDictionary objectForKey:
                  [[[NSString alloc] initWithFormat:@"World%d", i] autorelease]];
    NSLog(@"%d", w.worldNum);
    [w release];
}

取消注释“[un release];”行,readApplicationData工作正常,  但是当我试图像以后那样读取数据时:

NSMutableDictionary *dic = [GameDataManager sharedGameDataManager].worldInfoDictionary;
        for (int i = 1; i <= 10; i++) {

            NSString *key = [[NSString alloc] initWithFormat:@"World%d", i];    
            WorldInfoData *worldInfoData = [dic objectForKey:key];

            if (worldInfoData.worldNum == 1) {
                //......
            }
            [key release];
        }

此行之后:“WorldInfoData * worldInfoData = [dic objectForKey:key];”,worldInfoData的类型 不是WorldInfoData *而是CCArray,因为CCArray没有属性 worldNum,它崩溃了......

1 个答案:

答案 0 :(得分:0)

首先,我建议在启用Zombie检测的情况下运行您的应用程序。

您会发现通知您过度释放'w'。

WorldInfoData * w = [worldInfoDictionary objectForKey:
                         [[[NSString alloc] initWithFormat:@"World%d", i] autorelease]];
NSLog(@"%d", w.worldNum);
[w release];

您将'w'添加到自动释放池,但随后在其上显式调用release。我猜想摆脱[w发布]; line会解决您的问题,或者不会在自动释放池中添加“w”。